From 3445a85aad5c595a7e2d666950fdba53d19255b3 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Fri, 27 Jul 2018 18:35:21 -0700 Subject: [PATCH 01/97] initial progress on vesting spec --- docs/spec/auth/vesting.md | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/spec/auth/vesting.md diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md new file mode 100644 index 000000000..051595357 --- /dev/null +++ b/docs/spec/auth/vesting.md @@ -0,0 +1,88 @@ +## Vesting + +### Intro and Requirements + +This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. +The requirements for this vested account is that it should be capable of being initialized during genesis with +a starting balance X and a vesting blocknumber N. The owner of this account should be able to delegate to validators, +but they cannot send their initial coins to other accounts. However; funds sent to this account, or fees and +inflation rewards from delegation should be spendable. Thus, the bank module's MsgSend handler should error if +a vested account is trying to send an amount `x > currentBalance - initialBalance` before block N. + +### Implementation + +##### Changes to x/auth Module + +The first change is to the Account interface to specify both the Account type and any parameters it needs. + +```go +// Account is a standard account using a sequence number for replay protection +// and a pubkey for authentication. +type Account interface { + Type() string // returns the type of the account + + GetAddress() sdk.AccAddress + SetAddress(sdk.AccAddress) error // errors if already set. + + GetPubKey() crypto.PubKey // can return nil. + SetPubKey(crypto.PubKey) error + + GetAccountNumber() int64 + SetAccountNumber(int64) error + + GetSequence() int64 + SetSequence(int64) error + + GetCoins() sdk.Coins + SetCoins(sdk.Coins) error + + // Getter and setter methods for account params + // It is upto handler to use these appropriately + GetParams() map[string]interface{} + SetParams(map[string]interface{}) error +} +``` + +The `Type` method will allow handlers to determine what type of account is sending the message, and the +handler can then call `GetParams` to handle the specific account type using the parameters it expects to +exist in the parameter map. + +The `VestedAccount` will be an implementation of `Account` interface that wraps `BaseAccount` with +`Type() => "vested` and params, `GetParams() => {"Funds": initialBalance (sdk.Coins), "BlockLock": blockN (int64)}`. +`SetParams` will be disabled as we do not want to update params after vested account initialization. +The `VestedAccount` will also maintain an attribute called `FreeCoins` + + +`auth.AccountMapper` to handle vested accounts as well. Specific changes +are omitted in this doc for succinctness. + + +##### Changes to bank MsgSend Handler + +Since a vested account should be capable of doing everything but sending, the restriction should be +handled at the `bank.Keeper` level. Specifically in methods that are explicitly used for sending like +`sendCoins` and `inputOutputCoins`. These methods must check an account's `Type` method; if it is a vested +account (i.e. `acc.Type() == "vested"`): + +1. Check if `ctx.BlockHeight() < acc.GetParams()["BlockLock"]` + * If `true`, the account is still vesting +2. If account is still vesting, check that `(acc.GetCoins() - acc.GetParams()["Funds"] - amount).IsValid()`. + * This will check that amount trying to be spent will not come from initial balance. +3. If above checks pass, allow transaction to go through. Else, return sdk.Error. + +### Initializing at Genesis + +### Pros and Cons + +##### Pros + +- Easily Extensible. If more account types need to get added in the future or if developers building on top of SDK +want to handle multiple custom account types, they simply have to implement the `Account` interface with unique `Type` +and their custom parameters. +- Handlers (and their associated keepers) get to determine what types of accounts they will handle and can use the parameters +in Account interface to handle different accounts appropriately. + +##### Cons + +- Changes to `Account` interface +- Slightly more complex code in `bank.Keeper` functions From 39d1cf69b5240ea84692261411de02f40b8d1b5b Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Sun, 29 Jul 2018 19:29:54 -0700 Subject: [PATCH 02/97] simplify spec --- docs/spec/auth/vesting.md | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 051595357..3a3ef07e8 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -4,16 +4,15 @@ This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. The requirements for this vested account is that it should be capable of being initialized during genesis with -a starting balance X and a vesting blocknumber N. The owner of this account should be able to delegate to validators, -but they cannot send their initial coins to other accounts. However; funds sent to this account, or fees and -inflation rewards from delegation should be spendable. Thus, the bank module's MsgSend handler should error if -a vested account is trying to send an amount `x > currentBalance - initialBalance` before block N. +a starting balance X coins and a vesting blocknumber N. The owner of this account should be able to delegate to validators, +but they cannot send their coins to other accounts. Thus, the bank module's MsgSend handler should error if +a vested account is trying to send an amount before block N. ### Implementation ##### Changes to x/auth Module -The first change is to the Account interface to specify both the Account type and any parameters it needs. +The Account interface will specify both the Account type and any parameters it needs. ```go // Account is a standard account using a sequence number for replay protection @@ -48,12 +47,11 @@ handler can then call `GetParams` to handle the specific account type using the exist in the parameter map. The `VestedAccount` will be an implementation of `Account` interface that wraps `BaseAccount` with -`Type() => "vested` and params, `GetParams() => {"Funds": initialBalance (sdk.Coins), "BlockLock": blockN (int64)}`. -`SetParams` will be disabled as we do not want to update params after vested account initialization. -The `VestedAccount` will also maintain an attribute called `FreeCoins` +`Type() => "vested` and params, `GetParams() => {"BlockLock": blockN (int64)}`. +`SetParams` will be disabled as we do not want to update params after vested account initialization. -`auth.AccountMapper` to handle vested accounts as well. Specific changes +`auth.AccountMapper` will be modified handle vested accounts as well. Specific changes are omitted in this doc for succinctness. @@ -65,13 +63,25 @@ handled at the `bank.Keeper` level. Specifically in methods that are explicitly account (i.e. `acc.Type() == "vested"`): 1. Check if `ctx.BlockHeight() < acc.GetParams()["BlockLock"]` - * If `true`, the account is still vesting -2. If account is still vesting, check that `(acc.GetCoins() - acc.GetParams()["Funds"] - amount).IsValid()`. - * This will check that amount trying to be spent will not come from initial balance. -3. If above checks pass, allow transaction to go through. Else, return sdk.Error. +2. If `true`, the account is still vesting, return sdk.Error. Else, allow transaction to be processed as normal. ### Initializing at Genesis +To initialize both vested accounts and base accounts, the `GenesisAccount` struct will be: + +```go +type GenesisAccount struct { + Address sdk.AccAddress `json:"address"` + Coins sdk.Coins `json:"coins"` + Type string `json:"type"` + BlockLock int64 `json:"lock"` +} +``` + +During `InitChain`, the GenesisAccount's are decoded. If they have `Type == "vested`, a vested account with parameters => +`{"BlockLock": BlockLock}` gets created and put in initial state. Otherwise if `Type == "base"` a base account is created +and the `BlockLock` attribute of corresponding `GenesisAccount` is ignored. `InitChain` will panic on any other account types. + ### Pros and Cons ##### Pros From 69d1fe2fb18c0e6181a6ead92f3f9e031a6f688d Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Sun, 29 Jul 2018 19:33:17 -0700 Subject: [PATCH 03/97] clarify requirements --- docs/spec/auth/vesting.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 3a3ef07e8..c188f3f64 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -4,9 +4,9 @@ This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. The requirements for this vested account is that it should be capable of being initialized during genesis with -a starting balance X coins and a vesting blocknumber N. The owner of this account should be able to delegate to validators, -but they cannot send their coins to other accounts. Thus, the bank module's MsgSend handler should error if -a vested account is trying to send an amount before block N. +a starting balance X coins and a vesting blocknumber N. The owner of this account should be able to delegate to validators and vote, +however they cannot send their coins to other accounts until the account has fully vested. Thus, the bank module's MsgSend handler +should error if a vested account is trying to send an amount before block N. ### Implementation From 89494ef73eedb5e1ca0527eca161bf21030d3867 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Sun, 29 Jul 2018 19:35:23 -0700 Subject: [PATCH 04/97] improve readability --- docs/spec/auth/vesting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index c188f3f64..dcb07a18b 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -5,14 +5,14 @@ This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. The requirements for this vested account is that it should be capable of being initialized during genesis with a starting balance X coins and a vesting blocknumber N. The owner of this account should be able to delegate to validators and vote, -however they cannot send their coins to other accounts until the account has fully vested. Thus, the bank module's MsgSend handler +however they cannot send their coins to other accounts until the account has fully vested. Thus, the bank module's `MsgSend` handler should error if a vested account is trying to send an amount before block N. ### Implementation ##### Changes to x/auth Module -The Account interface will specify both the Account type and any parameters it needs. +The `Account` interface will specify both the Account type and any parameters it needs. ```go // Account is a standard account using a sequence number for replay protection From 6d75b69a5c937814b700a830045bdb710a5c8f67 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 30 Jul 2018 11:16:33 -0400 Subject: [PATCH 05/97] Initial ADR directory, templates, and ADR 001 --- docs/architecture/README.md | 27 ++++++++++++ docs/architecture/adr-001-signed-messages.md | 43 ++++++++++++++++++++ docs/architecture/adr.template.md | 43 ++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 docs/architecture/README.md create mode 100644 docs/architecture/adr-001-signed-messages.md create mode 100644 docs/architecture/adr.template.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 000000000..e2c46f647 --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,27 @@ +# Architecture Decision Records (ADR) + +This is a location to record all high-level architecture decisions in the Cosmos +SDK project. + +You can read more about the ADR concept in this [blog post](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t) +with a more detailed explanation [here](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). + +An ADR should provide: + +- Context on the relevant goals and the current state +- Proposed changes to achieve the goals +- Summary of pros and cons +- References +- Changelog + +You can see the template [here](./adr.template.md). + +Note the distinction between an ADR and a spec. The ADR provides the context, +intuition, reasoning, and justification for a change in architecture, or for the +architecture of something new. The spec is much more compressed and streamlined +summary of everything as it stands today. + +If recorded decisions turned out to be lacking, convene a discussion, record the +new decisions here, and then modify the code to match. + +Note the context/background should be written in the present tense. diff --git a/docs/architecture/adr-001-signed-messages.md b/docs/architecture/adr-001-signed-messages.md new file mode 100644 index 000000000..35b22e990 --- /dev/null +++ b/docs/architecture/adr-001-signed-messages.md @@ -0,0 +1,43 @@ +# ADR 001: Cosmos SDK Signed Messages + +## Changelog + +* {date}: {changelog} + +## Context + +> This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. + +{context body} + +## Decision + +> This section describes our response to these forces. It is stated in full sentences, with active voice. "We will ..." + +{decision body} + +## Status + +> A decision may be "proposed" if the project stakeholders haven't agreed with it yet, or "accepted" once it is agreed. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement. + +{Deprecated|Proposed|Accepted} + +## Consequences + +> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. + +### Positive + +{positive consequences} + +### Negative + +{negative consequences} + +### Neutral + +{neutral consequences} + +## References + +* {reference link} diff --git a/docs/architecture/adr.template.md b/docs/architecture/adr.template.md new file mode 100644 index 000000000..321c9a4bd --- /dev/null +++ b/docs/architecture/adr.template.md @@ -0,0 +1,43 @@ +# ADR {ADR-NUMBER}: {TITLE} + +## Changelog + +* {date}: {changelog} + +## Context + +> This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. + +{context body} + +## Decision + +> This section describes our response to these forces. It is stated in full sentences, with active voice. "We will ..." + +{decision body} + +## Status + +> A decision may be "proposed" if the project stakeholders haven't agreed with it yet, or "accepted" once it is agreed. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement. + +{Deprecated|Proposed|Accepted} + +## Consequences + +> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. + +### Positive + +{positive consequences} + +### Negative + +{negative consequences} + +### Neutral + +{neutral consequences} + +## References + +* {reference link} From 3fe0b73b03c8ad47ca868e450a2965758defdd1d Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 30 Jul 2018 12:19:39 -0400 Subject: [PATCH 06/97] Update ADR 001 context --- docs/architecture/adr-001-signed-messages.md | 24 ++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/architecture/adr-001-signed-messages.md b/docs/architecture/adr-001-signed-messages.md index 35b22e990..a1343dfff 100644 --- a/docs/architecture/adr-001-signed-messages.md +++ b/docs/architecture/adr-001-signed-messages.md @@ -2,13 +2,25 @@ ## Changelog -* {date}: {changelog} - ## Context -> This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. +Having the ability to sign messages off-chain has proven to be a fundamental aspect +of nearly any blockchain. The notion of signing messages off-chain has many +added benefits such as saving on computational costs and reducing transaction +throughput and overhead. Within the context of the Cosmos SDK, some of the major +applications of signing such data includes, but is not limited to, providing a +cryptographic secure and verifiable means of proving validator identity and +possibly associating it with some other framework or organization. In addition, +having the ability to sign Cosmos SDK messages with a Ledger device. -{context body} +A standardized protocol for hashing and signing messages that can be implemented +by the Cosmos SDK and any third-party organization is needed the subscribes to +the following: + +* A specification of structured data +* A framework for encoding structured data +* A cryptographic secure hashing and signing algorithm +* A framework for supporting extensions and domain separation ## Decision @@ -18,9 +30,7 @@ ## Status -> A decision may be "proposed" if the project stakeholders haven't agreed with it yet, or "accepted" once it is agreed. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement. - -{Deprecated|Proposed|Accepted} +Proposed. ## Consequences From f875b446e1e26fd0b0a008f7905aae3c8803be9e Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 30 Jul 2018 12:47:26 -0400 Subject: [PATCH 07/97] Add notes on replay protection and algos --- docs/architecture/adr-001-signed-messages.md | 27 ++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/architecture/adr-001-signed-messages.md b/docs/architecture/adr-001-signed-messages.md index a1343dfff..a00bf65c2 100644 --- a/docs/architecture/adr-001-signed-messages.md +++ b/docs/architecture/adr-001-signed-messages.md @@ -22,9 +22,31 @@ the following: * A cryptographic secure hashing and signing algorithm * A framework for supporting extensions and domain separation +This record is only concerned with the rationale and the standardized implementation +of Cosmos SDK signed messages. It does **not** concern itself with the concept of +replay attacks as that will be left up to the higher-level application implementation. +If you view signed messages in the means of authorizing some action or data, then +such an application would have to either treat this as idempotent or have mechanisms +in place to reject known signed messages. + +TODO: Should we bake in replay protection into the protocol? + ## Decision -> This section describes our response to these forces. It is stated in full sentences, with active voice. "We will ..." +> The proposed implementation is motivated by EIP-7121 and in general +Ethereum's `eth_sign` method2. + +### Preliminary + +We will a have Cosmos SDK message signing protocol that consists of `TMHASH`, which is +`SHA-256` with all but the first 20 bytes truncated, as the hashing algorithm and +`secp256k1` as the signing algorithm. + +Note, our goal here is not to provide context and reasoning about why necessarily +these algorithms were chosen apart from the fact they are the defacto algorithms +used in Tendermint and the Cosmos SDK and that they satisfy our needs for such +algorithms such as having resistance to second pre-image attacks and collision, +as well as being deterministic and uniform. {decision body} @@ -50,4 +72,5 @@ Proposed. ## References -* {reference link} +1. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md +2. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign \ No newline at end of file From 41130f87422dcb401b2a18a8d730724c22cd8510 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 30 Jul 2018 13:25:44 -0700 Subject: [PATCH 08/97] Addressed basic comments --- docs/spec/auth/vesting.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index dcb07a18b..1f72b48e5 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -4,9 +4,9 @@ This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. The requirements for this vested account is that it should be capable of being initialized during genesis with -a starting balance X coins and a vesting blocknumber N. The owner of this account should be able to delegate to validators and vote, +a starting balance X coins and a vesting blocktime T. The owner of this account should be able to delegate to validators and vote, however they cannot send their coins to other accounts until the account has fully vested. Thus, the bank module's `MsgSend` handler -should error if a vested account is trying to send an amount before block N. +should error if a vested account is trying to send an amount before time T. ### Implementation @@ -36,9 +36,10 @@ type Account interface { SetCoins(sdk.Coins) error // Getter and setter methods for account params + // Parameters can be understood to be a map[string]interface{} with encoded keys and vals in store // It is upto handler to use these appropriately - GetParams() map[string]interface{} - SetParams(map[string]interface{}) error + GetParams([]byte) []byte + SetParams([]byte, []byte) error } ``` @@ -47,7 +48,7 @@ handler can then call `GetParams` to handle the specific account type using the exist in the parameter map. The `VestedAccount` will be an implementation of `Account` interface that wraps `BaseAccount` with -`Type() => "vested` and params, `GetParams() => {"BlockLock": blockN (int64)}`. +`Type() => "vested` and params, `GetParams() => {"TimeLock": N (int64)}`. `SetParams` will be disabled as we do not want to update params after vested account initialization. @@ -62,7 +63,7 @@ handled at the `bank.Keeper` level. Specifically in methods that are explicitly `sendCoins` and `inputOutputCoins`. These methods must check an account's `Type` method; if it is a vested account (i.e. `acc.Type() == "vested"`): -1. Check if `ctx.BlockHeight() < acc.GetParams()["BlockLock"]` +1. Check if `ctx.BlockHeader().Time < acc.GetParams()["BlockLock"]` 2. If `true`, the account is still vesting, return sdk.Error. Else, allow transaction to be processed as normal. ### Initializing at Genesis @@ -71,16 +72,16 @@ To initialize both vested accounts and base accounts, the `GenesisAccount` struc ```go type GenesisAccount struct { - Address sdk.AccAddress `json:"address"` - Coins sdk.Coins `json:"coins"` - Type string `json:"type"` - BlockLock int64 `json:"lock"` + Address sdk.AccAddress `json:"address"` + Coins sdk.Coins `json:"coins"` + Type string `json:"type"` + TimeLock int64 `json:"lock"` } ``` During `InitChain`, the GenesisAccount's are decoded. If they have `Type == "vested`, a vested account with parameters => -`{"BlockLock": BlockLock}` gets created and put in initial state. Otherwise if `Type == "base"` a base account is created -and the `BlockLock` attribute of corresponding `GenesisAccount` is ignored. `InitChain` will panic on any other account types. +`{"TimeLock": N}` gets created and put in initial state. Otherwise if `Type == "base"` a base account is created +and the `TimeLock` attribute of corresponding `GenesisAccount` is ignored. `InitChain` will panic on any other account types. ### Pros and Cons From 02a7552f1840efb26a9c39dab9879604c74c28f3 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 30 Jul 2018 16:59:58 -0400 Subject: [PATCH 09/97] Remove ADR 001 and related directories/files --- docs/architecture/README.md | 27 ------- docs/architecture/adr-001-signed-messages.md | 76 -------------------- docs/architecture/adr.template.md | 43 ----------- 3 files changed, 146 deletions(-) delete mode 100644 docs/architecture/README.md delete mode 100644 docs/architecture/adr-001-signed-messages.md delete mode 100644 docs/architecture/adr.template.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md deleted file mode 100644 index e2c46f647..000000000 --- a/docs/architecture/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Architecture Decision Records (ADR) - -This is a location to record all high-level architecture decisions in the Cosmos -SDK project. - -You can read more about the ADR concept in this [blog post](https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0#.78xhdix6t) -with a more detailed explanation [here](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). - -An ADR should provide: - -- Context on the relevant goals and the current state -- Proposed changes to achieve the goals -- Summary of pros and cons -- References -- Changelog - -You can see the template [here](./adr.template.md). - -Note the distinction between an ADR and a spec. The ADR provides the context, -intuition, reasoning, and justification for a change in architecture, or for the -architecture of something new. The spec is much more compressed and streamlined -summary of everything as it stands today. - -If recorded decisions turned out to be lacking, convene a discussion, record the -new decisions here, and then modify the code to match. - -Note the context/background should be written in the present tense. diff --git a/docs/architecture/adr-001-signed-messages.md b/docs/architecture/adr-001-signed-messages.md deleted file mode 100644 index a00bf65c2..000000000 --- a/docs/architecture/adr-001-signed-messages.md +++ /dev/null @@ -1,76 +0,0 @@ -# ADR 001: Cosmos SDK Signed Messages - -## Changelog - -## Context - -Having the ability to sign messages off-chain has proven to be a fundamental aspect -of nearly any blockchain. The notion of signing messages off-chain has many -added benefits such as saving on computational costs and reducing transaction -throughput and overhead. Within the context of the Cosmos SDK, some of the major -applications of signing such data includes, but is not limited to, providing a -cryptographic secure and verifiable means of proving validator identity and -possibly associating it with some other framework or organization. In addition, -having the ability to sign Cosmos SDK messages with a Ledger device. - -A standardized protocol for hashing and signing messages that can be implemented -by the Cosmos SDK and any third-party organization is needed the subscribes to -the following: - -* A specification of structured data -* A framework for encoding structured data -* A cryptographic secure hashing and signing algorithm -* A framework for supporting extensions and domain separation - -This record is only concerned with the rationale and the standardized implementation -of Cosmos SDK signed messages. It does **not** concern itself with the concept of -replay attacks as that will be left up to the higher-level application implementation. -If you view signed messages in the means of authorizing some action or data, then -such an application would have to either treat this as idempotent or have mechanisms -in place to reject known signed messages. - -TODO: Should we bake in replay protection into the protocol? - -## Decision - -> The proposed implementation is motivated by EIP-7121 and in general -Ethereum's `eth_sign` method2. - -### Preliminary - -We will a have Cosmos SDK message signing protocol that consists of `TMHASH`, which is -`SHA-256` with all but the first 20 bytes truncated, as the hashing algorithm and -`secp256k1` as the signing algorithm. - -Note, our goal here is not to provide context and reasoning about why necessarily -these algorithms were chosen apart from the fact they are the defacto algorithms -used in Tendermint and the Cosmos SDK and that they satisfy our needs for such -algorithms such as having resistance to second pre-image attacks and collision, -as well as being deterministic and uniform. - -{decision body} - -## Status - -Proposed. - -## Consequences - -> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. - -### Positive - -{positive consequences} - -### Negative - -{negative consequences} - -### Neutral - -{neutral consequences} - -## References - -1. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md -2. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign \ No newline at end of file diff --git a/docs/architecture/adr.template.md b/docs/architecture/adr.template.md deleted file mode 100644 index 321c9a4bd..000000000 --- a/docs/architecture/adr.template.md +++ /dev/null @@ -1,43 +0,0 @@ -# ADR {ADR-NUMBER}: {TITLE} - -## Changelog - -* {date}: {changelog} - -## Context - -> This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. - -{context body} - -## Decision - -> This section describes our response to these forces. It is stated in full sentences, with active voice. "We will ..." - -{decision body} - -## Status - -> A decision may be "proposed" if the project stakeholders haven't agreed with it yet, or "accepted" once it is agreed. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement. - -{Deprecated|Proposed|Accepted} - -## Consequences - -> This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. - -### Positive - -{positive consequences} - -### Negative - -{negative consequences} - -### Neutral - -{neutral consequences} - -## References - -* {reference link} From da0d907d12fa27d0aa459d376ad4d6cf44590c2c Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 31 Jul 2018 09:38:29 -0400 Subject: [PATCH 10/97] Update ICS cosmos signed messages --- docs/ics/ics-xxx-signed-messages.md | 144 ++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 docs/ics/ics-xxx-signed-messages.md diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md new file mode 100644 index 000000000..e7d4e1a58 --- /dev/null +++ b/docs/ics/ics-xxx-signed-messages.md @@ -0,0 +1,144 @@ +# ICS XXX: Cosmos Signed Messages + +>TODO: Replace with valid ICS number and possibly move to new location. + +## Changelog + +## Abstract + +Having the ability to sign messages off-chain has proven to be a fundamental aspect +of nearly any blockchain. The notion of signing messages off-chain has many +added benefits such as saving on computational costs and reducing transaction +throughput and overhead. Within the context of the Cosmos, some of the major +applications of signing such data includes, but is not limited to, providing a +cryptographic secure and verifiable means of proving validator identity and +possibly associating it with some other framework or organization. In addition, +having the ability to sign Cosmos messages with a Ledger or similar HSM device. + +A standardized protocol for hashing, signing, and verifying messages that can be +implemented by the Cosmos SDK and other third-party organizations is needed. Such a +standardized protocol subscribes to the following: + +* Contains a specification of machine-verifiable and human-readable typed structured data +* Contains a framework for deterministic and injective encoding of structured data +* Utilizes cryptographic secure hashing and signing algorithms +* A framework for supporting extensions and domain separation +* Is invulnerable to chosen ciphertext attacks +* Has protection against potentially signing transactions a user did not intend to + +This specification is only concerned with the rationale and the standardized +implementation of Cosmos signed messages. It does **not** concern itself with the +concept of replay attacks as that will be left up to the higher-level application +implementation. If you view signed messages in the means of authorizing some +action or data, then such an application would have to either treat this as +idempotent or have mechanisms in place to reject known signed messages. + +## Specification + +> The proposed implementation is motivated and borrows heavily from EIP-7121 +and in general Ethereum's `eth_sign` and `eth_signTypedData` methods2. + +### Preliminary + +We will a have Cosmos SDK message signing protocol that consists of using `SHA-256`, +as the hashing algorithm and `secp256k1` as the signing algorithm. + +Note, our goal here is not to provide context and reasoning about why necessarily +these algorithms were chosen apart from the fact they are the defacto algorithms +used in Tendermint and the Cosmos SDK and that they satisfy our needs for such +cryptographic algorithms such as having resistance to collision and second +pre-image attacks, as well as being deterministic and uniform. + +### Encoding + +Our goal is to create a deterministic, injective, machine-verifiable means of +encoding human-readable typed and structured data. + +Let us consider the set of signed messages to be: `B ∪ S`, where `B` is the set +of byte strings and `S` is the set of human-readable typed structures. Thus, the +set can can be encoded in a deterministic and injective way via the following +rules, where `||` denotes concatenation: + +* `encode(b : B)` = `p1 || bytes("Signed Cosmos SDK Message: \n") || l || b`, where + * `l`: little endian uint64 encoding of the length of `b` + * `p1`: prefix to distinguish from normal transactions and other encoding cases +* `encode(s : S, domainSeparator : B)` = `p2 || domainSeparator || amino(s)`, where + * `domainSeparator`: 32 byte encoding of the domain separator [see below](###DomainSeparator) + * `p2`: prefix to distinguish from normal transactions and other encoding cases + +> TODO: Figure out byte(s) prefix in the encoding to not have collisions with +typical transaction signatures (JSON-encoded) and to distinguish the individual +cases. This may require introducing prefixes to transactions. + +#### Assumptions + +`amino` is deterministic and seems to be injective -- at least when when +concrete types are registered. Can we rely on this mechanism or do we need a +custom true injective encoding? + +> TODO: Do we need to implement a custom encoding scheme instead of or atop +amino similar or equal to EIP-712 `hashStruct`? As far as I know, this is mostly +due to providing Soldity efficiencies and addressing limitations. + +### DomainSeparator + +Encoding structures can still lead to potential collisions and while this may be +ok or even desired, it introduces a concern in that it could lead to two compatible +signatures. The domain separator prevents collisions of otherwise identical +structures. It is designed to unique per application use and is directly used in +the signature encoding itself. The domain separator is also extensible where the +protocol and application designer may introduce or omit fields to their liking, +but we will provide a typical structure that can be used for proper separation +of concerns: + +```golang +type DomainSeparator struct { + name string // A user readable name of the signing origin or application. + chainID string // The corresponding Cosmos chain identifier. + version uint16 // Version of the domain separator. A single major version should suffice. + salt []byte // Random data to further provide disambiguation. +} +``` + +Application designers may choose to omit or introduce additional fields to a +domain separator. However, users should provided with the exact information for +which they will be signing (i.e. a user should always know the chain ID they are +signing for). + +Given the set of all domain separators, the encoding of the domain separator +is as follows: + +* `encode(domainSeparator : B)` = `sha256(amino(domainSeparator))` + +## API + +We now formalize a standard set of APIs that providers must implement: + +``` +cosmosSignBytes(b : B, addr : B) { + return secp256k1Sign(sha256(encode(b)), addressPrivKey(addr)) +} +``` + +``` +cosmosSignBytesPass(b : B, pass : B) { + return secp256k1Sign(sha256(encode(b)), passPrivKey(addr)) +} +``` + +``` +cosmosSignTyped(s : S, domainSeparator : B, addr : B) { + return secp256k1Sign(sha256(encode(s, domainSeparator)), addressPrivKey(addr)) +} +``` + +``` +cosmosSignTypedPass(s : S, domainSeparator : B, pass : B) { + return secp256k1Sign(sha256(encode(s, domainSeparator)), passPrivKey(addr)) +} +``` + +## References + +1. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md +2. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign From fd64da85878310f7bc3a46dd6c9a0e89a12258aa Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Tue, 31 Jul 2018 10:04:21 -0400 Subject: [PATCH 11/97] Update assumptions --- docs/ics/ics-xxx-signed-messages.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index e7d4e1a58..751605056 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -76,6 +76,12 @@ cases. This may require introducing prefixes to transactions. concrete types are registered. Can we rely on this mechanism or do we need a custom true injective encoding? +User-agents such Voyager, Metamask, and Ledger may provide human-readable and +structured data, but this data must be consistent in terms of the field types +and structure itself encoded via `amino`. This would require said applications +to have an `amino` implementation. This may yet further warrant a simple custom +encoding. + > TODO: Do we need to implement a custom encoding scheme instead of or atop amino similar or equal to EIP-712 `hashStruct`? As far as I know, this is mostly due to providing Soldity efficiencies and addressing limitations. From d4d7658166100a156a76f8b29c6a1d1f3bc5ea99 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Tue, 31 Jul 2018 18:11:19 -0700 Subject: [PATCH 12/97] New idea for spec --- docs/spec/auth/vesting.md | 129 +++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 70 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 1f72b48e5..87194ce8e 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -2,98 +2,87 @@ ### Intro and Requirements -This paper specifies changes to the auth and bank modules to implement vested accounts for the Cosmos Hub. -The requirements for this vested account is that it should be capable of being initialized during genesis with -a starting balance X coins and a vesting blocktime T. The owner of this account should be able to delegate to validators and vote, -however they cannot send their coins to other accounts until the account has fully vested. Thus, the bank module's `MsgSend` handler -should error if a vested account is trying to send an amount before time T. +This paper specifies changes to the auth and bank modules to implement vesting accounts for the Cosmos Hub. +The requirements for this vesting account is that it should be capable of being initialized during genesis with +a starting balance X coins and a vesting blocktime T. The owner of this account should be able to delegate to validators +and vote with locked coins, however they cannot send locked coins to other accounts until those coins have been unlocked. +The vesting account should also be able to spend any coins it receives from other users or from fees/inflation rewards. +Thus, the bank module's `MsgSend` handler should error if a vesting account is trying to send an amount that exceeds their +unlocked coin amount. ### Implementation -##### Changes to x/auth Module - -The `Account` interface will specify both the Account type and any parameters it needs. +##### Vesting Account implementation ```go -// Account is a standard account using a sequence number for replay protection -// and a pubkey for authentication. -type Account interface { - Type() string // returns the type of the account +type VestingAccount interface { + Account + AssertIsVestingAccount() // existence implies that account is vesting. +} - GetAddress() sdk.AccAddress - SetAddress(sdk.AccAddress) error // errors if already set. +// Implements Vesting Account +// Continuously vests by unlocking coins linearly with respect to time +type ContinuousVestingAccount struct { + BaseAccount + OriginalCoins sdk.Coins + ReceivedCoins sdk.Coins + StartTime int64 + EndTime int64 +} - GetPubKey() crypto.PubKey // can return nil. - SetPubKey(crypto.PubKey) error - - GetAccountNumber() int64 - SetAccountNumber(int64) error - - GetSequence() int64 - SetSequence(int64) error - - GetCoins() sdk.Coins - SetCoins(sdk.Coins) error - - // Getter and setter methods for account params - // Parameters can be understood to be a map[string]interface{} with encoded keys and vals in store - // It is upto handler to use these appropriately - GetParams([]byte) []byte - SetParams([]byte, []byte) error +func (vacc ContinuousVestingAccount) ConvertAccount() BaseAccount { + if T > vacc.EndTime { + // Convert to BaseAccount + } } ``` -The `Type` method will allow handlers to determine what type of account is sending the message, and the -handler can then call `GetParams` to handle the specific account type using the parameters it expects to -exist in the parameter map. +The `VestingAccount` interface is used purely to assert that an account is a vesting account like so: -The `VestedAccount` will be an implementation of `Account` interface that wraps `BaseAccount` with -`Type() => "vested` and params, `GetParams() => {"TimeLock": N (int64)}`. -`SetParams` will be disabled as we do not want to update params after vested account initialization. +```go +vacc, ok := acc.(VestingAccount); ok +``` +The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalCoins`, `ReceivedCoins`, +`StartTime`, and `EndTime` to calculate how many coins are sendable at any given point. Once the account has fully vested, +the next `bank.MsgSend` will convert the account into a `BaseAccount` and store it in state as such from that point on. +Since the vesting restrictions need to be implemented on a per-module basis, the `ContinuouosVestingAccount` implements +the `Account` interface exactly like `BaseAccount`. -`auth.AccountMapper` will be modified handle vested accounts as well. Specific changes -are omitted in this doc for succinctness. +##### Changes to Keepers/Handler - -##### Changes to bank MsgSend Handler - -Since a vested account should be capable of doing everything but sending, the restriction should be +Since a vesting account should be capable of doing everything but sending with its locked coins, the restriction should be handled at the `bank.Keeper` level. Specifically in methods that are explicitly used for sending like -`sendCoins` and `inputOutputCoins`. These methods must check an account's `Type` method; if it is a vested -account (i.e. `acc.Type() == "vested"`): +`sendCoins` and `inputOutputCoins`. These methods must check that an account is a vesting account using the check described above. +NOTE: `Now = ctx.BlockHeader().Time` -1. Check if `ctx.BlockHeader().Time < acc.GetParams()["BlockLock"]` -2. If `true`, the account is still vesting, return sdk.Error. Else, allow transaction to be processed as normal. +1. If `Now < vacc.EndTime` + 1. Calculate `SendableCoins := ReceivedCoins + OriginalCoins * (Now - StartTime)/(EndTime - StartTime))` + - NOTE: `SendableCoins` may be greater than total coins in account. This is because coins can be subtracted by staking module. + `SendableCoins` denotes maximum coins allowed to be spent right now. + 2. If `msg.Amount > SendableCoins`, return sdk.Error. Else, allow transaction to process normally. +2. Else: + 1. Convert account to `BaseAccount` and process normally. + +Coins that are sent to a vesting account after initialization either through users sending them coins or through fees/inflation rewards +should be spendable immediately after receiving them. Thus, handlers (like staking or bank) that send coins that a vesting account did not +originally own should increment `ReceivedCoins` by the amount sent. + +WARNING: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account +unbonds from a validator, their tokens should be added back to account but `ReceivedCoins` SHOULD NOT be incremented. +However when the staking handler is handing out fees or inflation rewards, then `ReceivedCoins` SHOULD be incremented. ### Initializing at Genesis -To initialize both vested accounts and base accounts, the `GenesisAccount` struct will be: +To initialize both vesting accounts and base accounts, the `GenesisAccount` struct will be: ```go type GenesisAccount struct { - Address sdk.AccAddress `json:"address"` - Coins sdk.Coins `json:"coins"` - Type string `json:"type"` - TimeLock int64 `json:"lock"` + Address sdk.AccAddress `json:"address"` + Coins sdk.Coins `json:"coins"` + EndTime int64 `json:"lock"` } ``` -During `InitChain`, the GenesisAccount's are decoded. If they have `Type == "vested`, a vested account with parameters => -`{"TimeLock": N}` gets created and put in initial state. Otherwise if `Type == "base"` a base account is created -and the `TimeLock` attribute of corresponding `GenesisAccount` is ignored. `InitChain` will panic on any other account types. - -### Pros and Cons - -##### Pros - -- Easily Extensible. If more account types need to get added in the future or if developers building on top of SDK -want to handle multiple custom account types, they simply have to implement the `Account` interface with unique `Type` -and their custom parameters. -- Handlers (and their associated keepers) get to determine what types of accounts they will handle and can use the parameters -in Account interface to handle different accounts appropriately. - -##### Cons - -- Changes to `Account` interface -- Slightly more complex code in `bank.Keeper` functions +During `InitChain`, the GenesisAccounts are decoded. If `EndTime == 0`, a BaseAccount gets created and put in Genesis state. +Otherwise a vesting account is created with `StartTime = RequestInitChain.Time`, `EndTime = gacc.EndTime`, and `OriginalCoins = Coins`. From 00e116c0c72bb2f7a847e94e7f3a587aa2500df7 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 1 Aug 2018 14:53:34 -0400 Subject: [PATCH 13/97] Update preliminary --- docs/ics/ics-xxx-signed-messages.md | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 751605056..89efeb74f 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -40,8 +40,10 @@ and in general Ethereum's `eth_sign` and `eth_signTypedData` methods2 ### Preliminary -We will a have Cosmos SDK message signing protocol that consists of using `SHA-256`, -as the hashing algorithm and `secp256k1` as the signing algorithm. +The Cosmos message signing protocol will be parameterized with a cryptographic +secure hashing algorithm `SHA-256` and a signing algorithm `S` that contains +the operations `sign` and `verify` which provide a digital signature over a set +of bytes and verification of a signature respectively. Note, our goal here is not to provide context and reasoning about why necessarily these algorithms were chosen apart from the fact they are the defacto algorithms @@ -70,22 +72,6 @@ rules, where `||` denotes concatenation: typical transaction signatures (JSON-encoded) and to distinguish the individual cases. This may require introducing prefixes to transactions. -#### Assumptions - -`amino` is deterministic and seems to be injective -- at least when when -concrete types are registered. Can we rely on this mechanism or do we need a -custom true injective encoding? - -User-agents such Voyager, Metamask, and Ledger may provide human-readable and -structured data, but this data must be consistent in terms of the field types -and structure itself encoded via `amino`. This would require said applications -to have an `amino` implementation. This may yet further warrant a simple custom -encoding. - -> TODO: Do we need to implement a custom encoding scheme instead of or atop -amino similar or equal to EIP-712 `hashStruct`? As far as I know, this is mostly -due to providing Soldity efficiencies and addressing limitations. - ### DomainSeparator Encoding structures can still lead to potential collisions and while this may be From 508c54d3cd0d0ca45256177cdfea70f68ee28bda Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 1 Aug 2018 15:38:54 -0400 Subject: [PATCH 14/97] Update API section to be more spec-defined --- docs/ics/ics-xxx-signed-messages.md | 67 ++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 89efeb74f..7844cb615 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -104,31 +104,56 @@ is as follows: ## API -We now formalize a standard set of APIs that providers must implement: +Application developers and designers should formalize a standard set of APIs that +adhere to the following specification: -``` -cosmosSignBytes(b : B, addr : B) { - return secp256k1Sign(sha256(encode(b)), addressPrivKey(addr)) -} -``` +
-``` -cosmosSignBytesPass(b : B, pass : B) { - return secp256k1Sign(sha256(encode(b)), passPrivKey(addr)) -} -``` +**cosmosSignBytes** -``` -cosmosSignTyped(s : S, domainSeparator : B, addr : B) { - return secp256k1Sign(sha256(encode(s, domainSeparator)), addressPrivKey(addr)) -} -``` +Params: +* `data`: arbitrary byte length data to sign +* `address`: 20 byte account address to sign data with -``` -cosmosSignTypedPass(s : S, domainSeparator : B, pass : B) { - return secp256k1Sign(sha256(encode(s, domainSeparator)), passPrivKey(addr)) -} -``` +Returns: +* `signature`: the Cosmos signature derived using `S` + +
+ +**cosmosSignBytesPass** + +Params: +* `data`: arbitrary byte length data to sign +* `address`: 20 byte account address to sign data with +* `password`: password of the account to sign data with + +Returns: +* `signature`: the Cosmos signature derived using `S` + +
+ +**cosmosSignTyped** + +Params: +* `domainSeparator`: the application domain separator to encode and sign +* `typedData`: type data structure to encode and sign +* `address`: 20 byte account address to sign data with + +Returns: +* `signature`: the Cosmos signature derived using `S` + +
+ +**cosmosSignTypedPass** + +Params: +* `domainSeparator`: the application domain separator to encode and sign +* `typedData`: type data structure to encode and sign +* `address`: 20 byte account address to sign data with +* `password`: password of the account to sign data with + +Returns: +* `signature`: the Cosmos signature derived using `S` ## References From 11abc3f4f4fb0e40bd1e4d538917c04b1623c149 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 2 Aug 2018 14:28:23 -0400 Subject: [PATCH 15/97] Update encoding and schema spec --- docs/ics/ics-xxx-signed-messages.md | 217 +++++++++++++++++++++++----- 1 file changed, 179 insertions(+), 38 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 7844cb615..77aab79b8 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -2,6 +2,19 @@ >TODO: Replace with valid ICS number and possibly move to new location. + * [Changelog](#changelog) + * [Abstract](#abstract) + * [Specification](#specification) + + [Preliminary](#preliminary) + + [Encoding](#encoding) + - [Schema](#schema) + - [encodeStruct](#encodestruct) + - [encodeSchema](#encodeschema) + - [encodeData](#encodedata) + + [DomainSeparator](#domainseparator) + * [API](#api) + * [References](#references) + ## Changelog ## Abstract @@ -56,51 +69,181 @@ pre-image attacks, as well as being deterministic and uniform. Our goal is to create a deterministic, injective, machine-verifiable means of encoding human-readable typed and structured data. -Let us consider the set of signed messages to be: `B ∪ S`, where `B` is the set -of byte strings and `S` is the set of human-readable typed structures. Thus, the +Let us consider the set of signed messages to be: `B ∪ TS`, where `B` is the set +of byte arrays and `TS` is the set of human-readable typed structures. Thus, the set can can be encoded in a deterministic and injective way via the following rules, where `||` denotes concatenation: -* `encode(b : B)` = `p1 || bytes("Signed Cosmos SDK Message: \n") || l || b`, where +* `encode(b : B)` = `0x0000 || bytes("Signed Cosmos SDK Message: \n") || l || b`, where + * `b`: the bytes to be signed * `l`: little endian uint64 encoding of the length of `b` - * `p1`: prefix to distinguish from normal transactions and other encoding cases -* `encode(s : S, domainSeparator : B)` = `p2 || domainSeparator || amino(s)`, where - * `domainSeparator`: 32 byte encoding of the domain separator [see below](###DomainSeparator) - * `p2`: prefix to distinguish from normal transactions and other encoding cases +* `encode(ds : TS, ts : TS)` = `0x000001 || encodeStruct(ds) || encodeStruct(ts)`, where + * `ds`: the application domain separator which is also a human-readable typed structure ([see below](###DomainSeparator)) + * `ts`: the human-readable typed structure to be signed -> TODO: Figure out byte(s) prefix in the encoding to not have collisions with -typical transaction signatures (JSON-encoded) and to distinguish the individual -cases. This may require introducing prefixes to transactions. +The prefix bytes disambiguate the encoding cases from one another as well as +separating them from collision of transactions to be signed. The `amino` +serialization protocol escapes the set of disambiguation and prefix bytes with a +single `0x00` byte so there should be no collision with those structures. + +#### Schema + +To achieve deterministic and injective encoding, Cosmos signed messages over +type structures will use an existing known standard -- [JSON schema](http://json-schema.org/). +The domain separator and typed structures to be encoded must be specified with +a schema adhering to the JSON schema [specification](http://json-schema.org/specification.html). + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "cosmos/signing/typeData/schema", + "title": "The Cosmos signed message typed data schema.", + "type": "object", + "definitions": { + "typeDef": { + "type": "array", + "items": { + "description": "The list of properties a schema definition contains.", + "type": "object", + "properties": { + "name": { + "description": "The name of the schema rule.", + "type": "string", + "minLength": 1 + }, + "description": { + "description": "The description of the schema rule.", + "type": "string" + }, + "type": { + "description": "The type of the schema rule.", + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "type" + ] + } + } + }, + "properties": { + "types": { + "type": "object", + "properties": { + "CosmosDomain": { + "description": "The application domain separator schema.", + "$ref": "#/definitions/typeDef" + } + }, + "additionalProperties": { + "description": "The application type schemas.", + "$ref": "#/definitions/typeDef" + }, + "required": [ + "CosmosDomain" + ] + }, + "primaryType": { + "description": "The name of primary message type to sign.", + "type": "string", + "minLength": 1 + }, + "domain": { + "description": "The domain separator to sign.", + "type": "object" + }, + "message": { + "description": "The message data to sign.", + "type": "object" + } + }, + "required": [ + "types", + "primaryType", + "domain", + "message" + ] +} +``` + +#### encodeStruct + +The specification of encoding a human-readable typed structures, which includes +the domain separator, is as follows, where `||` denotes concatenation: + +`encodeStruct(ts : TS)` = `sha256(sha256(encodeSchema(ts)) || sha256(encodeData(ts)))` + +**Note**: The typed structure `ts` should include the JSON instance and schema. + +#### encodeSchema + +The **schema** of a typed structure is encoded as the name of the type and the +concatenation of it's schema fields. If the schema internally references other +schemas, then those are appended to the encoding. In order to make the encoding +deterministic, the encoding should sort types by their type name in lexicographic +ascending order. The specification is as follows, where `||` denotes concatenation: + +`encodeSchema(ts : TS)` = `"typeName(" || name || " " || type || ", " || ... || ")"` + +e.g. +```json +"Address(address string)Coin(amount integer, denom string)Transaction(coin Coin, from Address, to Address)" +``` + +##### Alternatives + +1. Instead of concatenating schema signatures, we could also take each type +definition and insert them into a sorted JSON object and hash the byte +representation of that object. This would avoid having to perform weird +concatenations. + +#### encodeData + +The **data** of a typed structure is encoded as the concatenation of values in +the typed data sorted by the field names in lexicographic ascending order. The +specification is as follows, where `||` denotes concatenation: + +`encodeData(ts : TS)` = sha256(value1) || sha256(value2) || ... || sha256(valuen)` ### DomainSeparator Encoding structures can still lead to potential collisions and while this may be -ok or even desired, it introduces a concern in that it could lead to two compatible +okay or even desired, it introduces a concern in that it could lead to two compatible signatures. The domain separator prevents collisions of otherwise identical -structures. It is designed to unique per application use and is directly used in -the signature encoding itself. The domain separator is also extensible where the -protocol and application designer may introduce or omit fields to their liking, -but we will provide a typical structure that can be used for proper separation +structures. It is designed to be unique per application use and is directly used +in the signature encoding itself. The domain separator is also extensible where +the protocol and application designer may introduce or omit fields to their needs, +but we will provide a "standard" structure that can be used for proper separation of concerns: -```golang -type DomainSeparator struct { - name string // A user readable name of the signing origin or application. - chainID string // The corresponding Cosmos chain identifier. - version uint16 // Version of the domain separator. A single major version should suffice. - salt []byte // Random data to further provide disambiguation. +```json +{ + "types": { + "CosmosDomain": [ + { + "name": "name", + "description": "The name of the signing origin or application.", + "type": "string" + }, + { + "name": "chainID", + "description": "The corresponding Cosmos chain identifier.", + "type": "string", + }, + { + "name": "version", + "description": "The major version of the domain separator.", + "type": "integer", + }, + ], + }, } ``` -Application designers may choose to omit or introduce additional fields to a -domain separator. However, users should provided with the exact information for -which they will be signing (i.e. a user should always know the chain ID they are -signing for). - -Given the set of all domain separators, the encoding of the domain separator -is as follows: - -* `encode(domainSeparator : B)` = `sha256(amino(domainSeparator))` +**Note**: The user-agent should refuse signing if the `chainID` does not match +the currently active chain! ## API @@ -116,7 +259,7 @@ Params: * `address`: 20 byte account address to sign data with Returns: -* `signature`: the Cosmos signature derived using `S` +* `signature`: the Cosmos signature derived using signing algorithm `S`
@@ -128,32 +271,30 @@ Params: * `password`: password of the account to sign data with Returns: -* `signature`: the Cosmos signature derived using `S` +* `signature`: the Cosmos signature derived using signing algorithm `S`
**cosmosSignTyped** Params: -* `domainSeparator`: the application domain separator to encode and sign -* `typedData`: type data structure to encode and sign +* `typedData`: type typed data structure, including the domain separator, to encode and sign * `address`: 20 byte account address to sign data with Returns: -* `signature`: the Cosmos signature derived using `S` +* `signature`: the Cosmos signature derived using signing algorithm `S`
**cosmosSignTypedPass** Params: -* `domainSeparator`: the application domain separator to encode and sign -* `typedData`: type data structure to encode and sign +* `typedData`: type typed data structure, including the domain separator, to encode and sign * `address`: 20 byte account address to sign data with * `password`: password of the account to sign data with Returns: -* `signature`: the Cosmos signature derived using `S` +* `signature`: the Cosmos signature derived using signing algorithm `S` ## References From 43420936e574ec0d3200566b9162cb4ff56e15cc Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 2 Aug 2018 14:31:09 -0400 Subject: [PATCH 16/97] Fix link --- docs/ics/ics-xxx-signed-messages.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 77aab79b8..59fe8c1ad 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -78,7 +78,7 @@ rules, where `||` denotes concatenation: * `b`: the bytes to be signed * `l`: little endian uint64 encoding of the length of `b` * `encode(ds : TS, ts : TS)` = `0x000001 || encodeStruct(ds) || encodeStruct(ts)`, where - * `ds`: the application domain separator which is also a human-readable typed structure ([see below](###DomainSeparator)) + * `ds`: the application domain separator which is also a human-readable typed structure ([see below](#domainseparator)) * `ts`: the human-readable typed structure to be signed The prefix bytes disambiguate the encoding cases from one another as well as @@ -205,7 +205,7 @@ The **data** of a typed structure is encoded as the concatenation of values in the typed data sorted by the field names in lexicographic ascending order. The specification is as follows, where `||` denotes concatenation: -`encodeData(ts : TS)` = sha256(value1) || sha256(value2) || ... || sha256(valuen)` +`encodeData(ts : TS)` = sha256(value1) || sha256(value2) || ... || sha256(valuen)`, where value1 < value2 ### DomainSeparator From 9cfe2c59f1a1025fa3e5800c58d642113181e0eb Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 2 Aug 2018 14:35:54 -0400 Subject: [PATCH 17/97] Update schema --- docs/ics/ics-xxx-signed-messages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 59fe8c1ad..58776c31d 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -146,7 +146,7 @@ a schema adhering to the JSON schema [specification](http://json-schema.org/spec ] }, "primaryType": { - "description": "The name of primary message type to sign.", + "description": "The name of primary message type to sign. This is needed for when there is more than one type defined besides `CosmosDomain`.", "type": "string", "minLength": 1 }, From 10b2e830a224b00f5096c486ffdaec74b0ae29bf Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Fri, 3 Aug 2018 13:12:34 -0700 Subject: [PATCH 18/97] addressed comments, added formulas for easy verification --- docs/spec/auth/vesting.md | 108 +++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 30 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 87194ce8e..99a051284 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -2,11 +2,11 @@ ### Intro and Requirements -This paper specifies changes to the auth and bank modules to implement vesting accounts for the Cosmos Hub. -The requirements for this vesting account is that it should be capable of being initialized during genesis with -a starting balance X coins and a vesting blocktime T. The owner of this account should be able to delegate to validators +This paper specifies vesting account implementation for the Cosmos Hub. +The requirements for this vesting account is that it should be initialized during genesis with +a starting balance X coins and a vesting endtime T. The owner of this account should be able to delegate to validators and vote with locked coins, however they cannot send locked coins to other accounts until those coins have been unlocked. -The vesting account should also be able to spend any coins it receives from other users or from fees/inflation rewards. +The vesting account should also be able to spend any coins it receives from other users. Thus, the bank module's `MsgSend` handler should error if a vesting account is trying to send an amount that exceeds their unlocked coin amount. @@ -14,35 +14,40 @@ unlocked coin amount. ##### Vesting Account implementation +NOTE: `Now = ctx.BlockHeader().Time` + ```go type VestingAccount interface { Account AssertIsVestingAccount() // existence implies that account is vesting. + ConvertAccount(sdk.Context) BaseAccount } // Implements Vesting Account // Continuously vests by unlocking coins linearly with respect to time type ContinuousVestingAccount struct { BaseAccount - OriginalCoins sdk.Coins - ReceivedCoins sdk.Coins + OriginalCoins sdk.Coins // Coins in account on Initialization + ReceivedCoins sdk.Coins // Coins received from other accounts + + // StartTime and EndTime used to calculate how much of OriginalCoins is unlocked at any given point StartTime int64 EndTime int64 } -func (vacc ContinuousVestingAccount) ConvertAccount() BaseAccount { - if T > vacc.EndTime { - // Convert to BaseAccount - } -} +ConvertAccount(vacc ContinuousVestingAccount) (BaseAccount): + if Now > vacc.EndTime then // Convert to BaseAccount + ``` -The `VestingAccount` interface is used purely to assert that an account is a vesting account like so: +The `VestingAccount` interface is used to assert that an account is a vesting account like so: ```go vacc, ok := acc.(VestingAccount); ok ``` +as well as to convert to BaseAccount again once the account has fully vested. + The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalCoins`, `ReceivedCoins`, `StartTime`, and `EndTime` to calculate how many coins are sendable at any given point. Once the account has fully vested, the next `bank.MsgSend` will convert the account into a `BaseAccount` and store it in state as such from that point on. @@ -54,35 +59,78 @@ the `Account` interface exactly like `BaseAccount`. Since a vesting account should be capable of doing everything but sending with its locked coins, the restriction should be handled at the `bank.Keeper` level. Specifically in methods that are explicitly used for sending like `sendCoins` and `inputOutputCoins`. These methods must check that an account is a vesting account using the check described above. -NOTE: `Now = ctx.BlockHeader().Time` -1. If `Now < vacc.EndTime` - 1. Calculate `SendableCoins := ReceivedCoins + OriginalCoins * (Now - StartTime)/(EndTime - StartTime))` - - NOTE: `SendableCoins` may be greater than total coins in account. This is because coins can be subtracted by staking module. - `SendableCoins` denotes maximum coins allowed to be spent right now. - 2. If `msg.Amount > SendableCoins`, return sdk.Error. Else, allow transaction to process normally. -2. Else: - 1. Convert account to `BaseAccount` and process normally. +```go +if Now < vacc.EndTime: + // NOTE: SendableCoins may be greater than total coins in account because coins can be subtracted by staking module + // SendableCoins denotes maximum coins allowed to be spent. + SendableCoins := ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) + if msg.Amount > SendableCoins then fail -Coins that are sent to a vesting account after initialization either through users sending them coins or through fees/inflation rewards -should be spendable immediately after receiving them. Thus, handlers (like staking or bank) that send coins that a vesting account did not +else: account = ConvertAccount(account) // Account fully vested, convert to BaseAccount + +if msg.Amount > account.GetCoins() then fail // Must still check if account has enough coins, since SendableCoins does not check this. + +// All checks passed, send the coins +SendCoins(inputs, outputs) + +``` + +Coins that are sent to a vesting account after initialization by users sending them coins should be spendable +immediately after receiving them. Thus, handlers (like staking or bank) that send coins that a vesting account did not originally own should increment `ReceivedCoins` by the amount sent. -WARNING: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account -unbonds from a validator, their tokens should be added back to account but `ReceivedCoins` SHOULD NOT be incremented. +CONTRACT: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account unbonds from a validator, their tokens should be added back to account but `ReceivedCoins` SHOULD NOT be incremented. However when the staking handler is handing out fees or inflation rewards, then `ReceivedCoins` SHOULD be incremented. ### Initializing at Genesis -To initialize both vesting accounts and base accounts, the `GenesisAccount` struct will be: +To initialize both vesting accounts and base accounts, the `GenesisAccount` struct will include an EndTime. Accounts meant to be +BaseAccounts will have `EndTime = 0`. The `initChainer` method will parse the GenesisAccount into BaseAccounts and VestingAccounts +as appropriate. ```go type GenesisAccount struct { - Address sdk.AccAddress `json:"address"` - Coins sdk.Coins `json:"coins"` - EndTime int64 `json:"lock"` + Address sdk.AccAddress `json:"address"` + GenesisCoins sdk.Coins `json:"coins"` + EndTime int64 `json:"lock"` } + +initChainer: + for genesis_acc in GenesisAccounts: + if EndTime == 0 then // Create BaseAccount + else: + vesting_account = ContinuouslyVestingAccount{ + OriginalCoins: GenesisCoins, + StartTime: RequestInitChain.Time, + EndTime: EndTime, + } + // Add account to initial state ``` -During `InitChain`, the GenesisAccounts are decoded. If `EndTime == 0`, a BaseAccount gets created and put in Genesis state. -Otherwise a vesting account is created with `StartTime = RequestInitChain.Time`, `EndTime = gacc.EndTime`, and `OriginalCoins = Coins`. +### Formulas + +`OriginalCoins`: Amount of coins in account at Genesis + +`CurrentCoins`: Coins currently in the baseaccount (both locked and unlocked) + +`ReceivedCoins`: Coins received from other accounts (always unlocked) + +`LockedCoins`: Coins that are currently locked + +`Delegated`: Coins that have been delegated (no longer in account; may be locked or unlocked) + +`Sent`: Coins sent to other accounts (MUST be unlocked) + +Maximum amount of coins vesting schedule allows to be sent: + +`ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime)` +`ReceivedCoins + OriginalCoins - LockedCoins` + +Coins currently in Account: + +`CurrentCoins = OriginalCoins + ReceivedCoins - Delegated - Sent` + +**Maximum amount of coins spendable right now:** + +`min( ReceivedCoins + OriginalCoins - LockedCoins, CurrentCoins )` From 9c1918efdc04545297ff5b0c3f07da076fdc7e97 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Fri, 3 Aug 2018 13:16:41 -0700 Subject: [PATCH 19/97] improve readability --- docs/spec/auth/vesting.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 99a051284..d70c94b1f 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -62,14 +62,18 @@ handled at the `bank.Keeper` level. Specifically in methods that are explicitly ```go if Now < vacc.EndTime: - // NOTE: SendableCoins may be greater than total coins in account because coins can be subtracted by staking module + // NOTE: SendableCoins may be greater than total coins in account + // because coins can be subtracted by staking module // SendableCoins denotes maximum coins allowed to be spent. SendableCoins := ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) if msg.Amount > SendableCoins then fail -else: account = ConvertAccount(account) // Account fully vested, convert to BaseAccount +// Account fully vested, convert to BaseAccount +else: account = ConvertAccount(account) -if msg.Amount > account.GetCoins() then fail // Must still check if account has enough coins, since SendableCoins does not check this. +// Must still check if account has enough coins, +// since SendableCoins does not check this. +if msg.Amount > account.GetCoins() then fail // All checks passed, send the coins SendCoins(inputs, outputs) @@ -125,6 +129,7 @@ initChainer: Maximum amount of coins vesting schedule allows to be sent: `ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime)` + `ReceivedCoins + OriginalCoins - LockedCoins` Coins currently in Account: From d56e3a7ef919f1fc3b64bc028a08bf8cc2ab9652 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 6 Aug 2018 13:03:58 -0700 Subject: [PATCH 20/97] better pseudocode --- docs/spec/auth/vesting.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index d70c94b1f..3d2be53c3 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -35,8 +35,12 @@ type ContinuousVestingAccount struct { EndTime int64 } +// ConvertAccount converts VestingAccount into BaseAccount +// Will convert only after account has fully vested ConvertAccount(vacc ContinuousVestingAccount) (BaseAccount): - if Now > vacc.EndTime then // Convert to BaseAccount + if Now > vacc.EndTime: + account = NewBaseAccount(vacc.Address, vacc.OriginalCoins + vacc.ReceivedCoins) + return account ``` @@ -101,15 +105,22 @@ type GenesisAccount struct { } initChainer: - for genesis_acc in GenesisAccounts: - if EndTime == 0 then // Create BaseAccount - else: - vesting_account = ContinuouslyVestingAccount{ - OriginalCoins: GenesisCoins, + for gacc in GenesisAccounts: + baseAccount := BaseAccount{ + Address: gacc.Address, + Coins: gacc.GenesisCoins, + } + if gacc.EndTime != 0: + vestingAccount := ContinuouslyVestingAccount{ + BaseAccount: baseAccount, + OriginalCoins: gacc.GenesisCoins, StartTime: RequestInitChain.Time, - EndTime: EndTime, + EndTime: gacc.EndTime, } - // Add account to initial state + AddAccountToState(vestingAccount) + else: + AddAccountToState(baseAccount) + ``` ### Formulas From 2ac55ebb1dac3b53fe5eaf06daf757eecbb233e8 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 6 Aug 2018 15:23:47 -0700 Subject: [PATCH 21/97] even better pseudocode --- docs/spec/auth/vesting.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 3d2be53c3..3123e1da6 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -65,7 +65,7 @@ handled at the `bank.Keeper` level. Specifically in methods that are explicitly `sendCoins` and `inputOutputCoins`. These methods must check that an account is a vesting account using the check described above. ```go -if Now < vacc.EndTime: +if Now < vestingAccount.EndTime: // NOTE: SendableCoins may be greater than total coins in account // because coins can be subtracted by staking module // SendableCoins denotes maximum coins allowed to be spent. @@ -73,11 +73,12 @@ if Now < vacc.EndTime: if msg.Amount > SendableCoins then fail // Account fully vested, convert to BaseAccount -else: account = ConvertAccount(account) +else: + account = ConvertAccount(account) // Must still check if account has enough coins, // since SendableCoins does not check this. -if msg.Amount > account.GetCoins() then fail +if msg.Amount > account.GetCoins() then fail // All checks passed, send the coins SendCoins(inputs, outputs) From cd3d197cc12265b2d6ffeb92a0e56a654b4bd6a0 Mon Sep 17 00:00:00 2001 From: Rigel Date: Tue, 7 Aug 2018 13:55:09 -0400 Subject: [PATCH 22/97] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f7e2d0fd6..6a2526059 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,6 +10,7 @@ v If a checkbox is n/a - please still include it but + a little note why - [ ] Wrote tests - [ ] Added entries in `PENDING.md` that include links to the relevant issue or PR that most accurately describes the change. - [ ] Updated `cmd/gaia` and `examples/` +- [ ] Read PR `Files changed` in the github PR explorer ___________________________________ For Admin Use: - [ ] Added appropriate labels to PR (ex. wip, ready-for-review, docs) From feb9a22663546fc55bd627ae2a2b2d471697de72 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Tue, 7 Aug 2018 17:02:28 -0700 Subject: [PATCH 23/97] Cleaned up spec further --- docs/spec/auth/vesting.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 3123e1da6..b9535af05 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -21,6 +21,10 @@ type VestingAccount interface { Account AssertIsVestingAccount() // existence implies that account is vesting. ConvertAccount(sdk.Context) BaseAccount + + // Calculates total amount of unlocked coins released by vesting schedule + // May be larger than total coins in account right now + TotalUnlockedCoins(sdk.Context) sdk.Coins } // Implements Vesting Account @@ -37,10 +41,13 @@ type ContinuousVestingAccount struct { // ConvertAccount converts VestingAccount into BaseAccount // Will convert only after account has fully vested -ConvertAccount(vacc ContinuousVestingAccount) (BaseAccount): +ConvertAccount(vacc ContinuousVestingAccount, ctx sdk.Context) (BaseAccount): if Now > vacc.EndTime: - account = NewBaseAccount(vacc.Address, vacc.OriginalCoins + vacc.ReceivedCoins) - return account + return vacc.BaseAccount + +// Uses time in context to calculate total unlocked coins +TotalUnlockedCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins: + return ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) ``` @@ -69,8 +76,7 @@ if Now < vestingAccount.EndTime: // NOTE: SendableCoins may be greater than total coins in account // because coins can be subtracted by staking module // SendableCoins denotes maximum coins allowed to be spent. - SendableCoins := ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) - if msg.Amount > SendableCoins then fail + if msg.Amount > vestingAccount.TotalUnlockedCoins() then fail // Account fully vested, convert to BaseAccount else: @@ -148,6 +154,8 @@ Coins currently in Account: `CurrentCoins = OriginalCoins + ReceivedCoins - Delegated - Sent` +`CurrentCoins = vestingAccount.BaseAccount.GetCoins()` + **Maximum amount of coins spendable right now:** `min( ReceivedCoins + OriginalCoins - LockedCoins, CurrentCoins )` From 7539e212ee5f4dc7dfed4a746430a9e5ae1278b4 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Tue, 7 Aug 2018 17:04:22 -0700 Subject: [PATCH 24/97] more readable pseudo --- docs/spec/auth/vesting.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index b9535af05..a69a342e4 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -47,7 +47,8 @@ ConvertAccount(vacc ContinuousVestingAccount, ctx sdk.Context) (BaseAccount): // Uses time in context to calculate total unlocked coins TotalUnlockedCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins: - return ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) + unlockedCoins := ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) + return unlockedCoins ``` From aa01e9954c4d4936c2b02cbb45dcd81ed00408ff Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 9 Aug 2018 11:35:22 -0400 Subject: [PATCH 25/97] Simply Cosmos signed message spec (using TM canonical JSON) --- docs/ics/ics-xxx-signed-messages.md | 266 ++++++++-------------------- 1 file changed, 72 insertions(+), 194 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 58776c31d..50dd67c75 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -2,16 +2,11 @@ >TODO: Replace with valid ICS number and possibly move to new location. - * [Changelog](#changelog) + * [Changelog](#changelog) * [Abstract](#abstract) + * [Preliminary](#preliminary) * [Specification](#specification) - + [Preliminary](#preliminary) - + [Encoding](#encoding) - - [Schema](#schema) - - [encodeStruct](#encodestruct) - - [encodeSchema](#encodeschema) - - [encodeData](#encodedata) - + [DomainSeparator](#domainseparator) + * [Future Adaptations](#future-adaptations) * [API](#api) * [References](#references) @@ -32,7 +27,7 @@ A standardized protocol for hashing, signing, and verifying messages that can be implemented by the Cosmos SDK and other third-party organizations is needed. Such a standardized protocol subscribes to the following: -* Contains a specification of machine-verifiable and human-readable typed structured data +* Contains a specification of human-readable and machine-verifiable typed structured data * Contains a framework for deterministic and injective encoding of structured data * Utilizes cryptographic secure hashing and signing algorithms * A framework for supporting extensions and domain separation @@ -46,13 +41,7 @@ implementation. If you view signed messages in the means of authorizing some action or data, then such an application would have to either treat this as idempotent or have mechanisms in place to reject known signed messages. -## Specification - -> The proposed implementation is motivated and borrows heavily from EIP-7121 -and in general Ethereum's `eth_sign` and `eth_signTypedData` methods2. - -### Preliminary - +## Preliminary The Cosmos message signing protocol will be parameterized with a cryptographic secure hashing algorithm `SHA-256` and a signing algorithm `S` that contains the operations `sign` and `verify` which provide a digital signature over a set @@ -64,186 +53,101 @@ used in Tendermint and the Cosmos SDK and that they satisfy our needs for such cryptographic algorithms such as having resistance to collision and second pre-image attacks, as well as being deterministic and uniform. -### Encoding +## Specification -Our goal is to create a deterministic, injective, machine-verifiable means of -encoding human-readable typed and structured data. +Tendermint has a well established protocol for signing messages using a canonical +JSON representation as defined [here](https://github.com/tendermint/tendermint/blob/master/types/canonical_json.go). -Let us consider the set of signed messages to be: `B ∪ TS`, where `B` is the set -of byte arrays and `TS` is the set of human-readable typed structures. Thus, the -set can can be encoded in a deterministic and injective way via the following -rules, where `||` denotes concatenation: +An example of such a canonical JSON structure is Tendermint's vote structure: -* `encode(b : B)` = `0x0000 || bytes("Signed Cosmos SDK Message: \n") || l || b`, where - * `b`: the bytes to be signed - * `l`: little endian uint64 encoding of the length of `b` -* `encode(ds : TS, ts : TS)` = `0x000001 || encodeStruct(ds) || encodeStruct(ts)`, where - * `ds`: the application domain separator which is also a human-readable typed structure ([see below](#domainseparator)) - * `ts`: the human-readable typed structure to be signed +```golang +type CanonicalJSONVote struct { + ChainID string `json:"@chain_id"` + Type string `json:"@type"` + BlockID CanonicalJSONBlockID `json:"block_id"` + Height int64 `json:"height"` + Round int `json:"round"` + Timestamp string `json:"timestamp"` + VoteType byte `json:"type"` +} +``` -The prefix bytes disambiguate the encoding cases from one another as well as -separating them from collision of transactions to be signed. The `amino` -serialization protocol escapes the set of disambiguation and prefix bytes with a -single `0x00` byte so there should be no collision with those structures. +With such canonical JSON structures, the specification requires that they include +meta fields: `@chain_id` and `@type`. These meta fields are reserved and must be +included. They are both of type `string`. In addition, fields must be ordered +in lexicographically ascending order. -#### Schema +For the purposes of signing Cosmos messages, the `@chain_id` field must correspond +to the Cosmos chain identifier. The user-agent should **refuse** signing if the +`@chain_id` field does not match the currently active chain! The `@type` field +must equal the constant `"message"`. The `@type` field corresponds to the type of +structure the user will be signing in an application. For now, a user is only +allowed to sign bytes of valid ASCII text ([see here](https://github.com/tendermint/tendermint/blob/master/libs/common/string.go#L61-L74)). +However, this will change and evolve to support additional application-specific +structures that are human-readable and machine-verifiable ([see Future Adaptations](#futureadaptations)). -To achieve deterministic and injective encoding, Cosmos signed messages over -type structures will use an existing known standard -- [JSON schema](http://json-schema.org/). -The domain separator and typed structures to be encoded must be specified with -a schema adhering to the JSON schema [specification](http://json-schema.org/specification.html). +Thus, we can have a canonical JSON structure for signing Cosmos messages using +the [JSON schema](http://json-schema.org/) specification as such: ```json { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-04/schema#", "$id": "cosmos/signing/typeData/schema", "title": "The Cosmos signed message typed data schema.", "type": "object", - "definitions": { - "typeDef": { - "type": "array", - "items": { - "description": "The list of properties a schema definition contains.", - "type": "object", - "properties": { - "name": { - "description": "The name of the schema rule.", - "type": "string", - "minLength": 1 - }, - "description": { - "description": "The description of the schema rule.", - "type": "string" - }, - "type": { - "description": "The type of the schema rule.", - "type": "string", - "minLength": 1 - } - }, - "required": [ - "name", - "type" - ] - } - } - }, "properties": { - "types": { - "type": "object", - "properties": { - "CosmosDomain": { - "description": "The application domain separator schema.", - "$ref": "#/definitions/typeDef" - } - }, - "additionalProperties": { - "description": "The application type schemas.", - "$ref": "#/definitions/typeDef" - }, - "required": [ - "CosmosDomain" - ] - }, - "primaryType": { - "description": "The name of primary message type to sign. This is needed for when there is more than one type defined besides `CosmosDomain`.", + "@chain_id": { "type": "string", + "description": "The corresponding Cosmos chain identifier.", "minLength": 1 }, - "domain": { - "description": "The domain separator to sign.", - "type": "object" + "@type": { + "type": "string", + "description": "The message type. It must be 'message'.", + "enum": [ + "message" + ] }, - "message": { - "description": "The message data to sign.", - "type": "object" + "text": { + "type": "string", + "description": "The valid ASCII text to sign.", + "pattern": "^[\\x20-\\x7E]+$", + "minLength": 1 } }, "required": [ - "types", - "primaryType", - "domain", - "message" + "@chain_id", + "@type", + "text" ] } ``` -#### encodeStruct - -The specification of encoding a human-readable typed structures, which includes -the domain separator, is as follows, where `||` denotes concatenation: - -`encodeStruct(ts : TS)` = `sha256(sha256(encodeSchema(ts)) || sha256(encodeData(ts)))` - -**Note**: The typed structure `ts` should include the JSON instance and schema. - -#### encodeSchema - -The **schema** of a typed structure is encoded as the name of the type and the -concatenation of it's schema fields. If the schema internally references other -schemas, then those are appended to the encoding. In order to make the encoding -deterministic, the encoding should sort types by their type name in lexicographic -ascending order. The specification is as follows, where `||` denotes concatenation: - -`encodeSchema(ts : TS)` = `"typeName(" || name || " " || type || ", " || ... || ")"` - e.g. -```json -"Address(address string)Coin(amount integer, denom string)Transaction(coin Coin, from Address, to Address)" -``` - -##### Alternatives - -1. Instead of concatenating schema signatures, we could also take each type -definition and insert them into a sorted JSON object and hash the byte -representation of that object. This would avoid having to perform weird -concatenations. - -#### encodeData - -The **data** of a typed structure is encoded as the concatenation of values in -the typed data sorted by the field names in lexicographic ascending order. The -specification is as follows, where `||` denotes concatenation: - -`encodeData(ts : TS)` = sha256(value1) || sha256(value2) || ... || sha256(valuen)`, where value1 < value2 - -### DomainSeparator - -Encoding structures can still lead to potential collisions and while this may be -okay or even desired, it introduces a concern in that it could lead to two compatible -signatures. The domain separator prevents collisions of otherwise identical -structures. It is designed to be unique per application use and is directly used -in the signature encoding itself. The domain separator is also extensible where -the protocol and application designer may introduce or omit fields to their needs, -but we will provide a "standard" structure that can be used for proper separation -of concerns: - ```json { - "types": { - "CosmosDomain": [ - { - "name": "name", - "description": "The name of the signing origin or application.", - "type": "string" - }, - { - "name": "chainID", - "description": "The corresponding Cosmos chain identifier.", - "type": "string", - }, - { - "name": "version", - "description": "The major version of the domain separator.", - "type": "integer", - }, - ], - }, + "@chain_id": "1", + "@type": "message", + "text": "Hello, you can identify me as XYZ on keybase." } ``` -**Note**: The user-agent should refuse signing if the `chainID` does not match -the currently active chain! +## Future Adaptations + +As applications can vary greatly in domain, it will be vital to support both +domain separation and human-readable and machine-verifiable structures. + +Domain separation will allow for application developers to prevent collisions of +otherwise identical structures. It should be designed to be unique per application +use and should directly be used in the signature encoding itself. + +Human-readable and machine-verifiable structures will allow end users to sign +more complex structures, apart from just string messages, and still be able to +know exactly what they are signing (opposed to signing a bunch of arbitrary bytes). + +Thus, in the future, the Cosmos signing message specification will be expected +to expand upon it's canonical JSON structure to include such functionality. + ## API @@ -255,7 +159,7 @@ adhere to the following specification: **cosmosSignBytes** Params: -* `data`: arbitrary byte length data to sign +* `data`: the Cosmos signed message canonical JSON structure * `address`: 20 byte account address to sign data with Returns: @@ -266,30 +170,7 @@ Returns: **cosmosSignBytesPass** Params: -* `data`: arbitrary byte length data to sign -* `address`: 20 byte account address to sign data with -* `password`: password of the account to sign data with - -Returns: -* `signature`: the Cosmos signature derived using signing algorithm `S` - -
- -**cosmosSignTyped** - -Params: -* `typedData`: type typed data structure, including the domain separator, to encode and sign -* `address`: 20 byte account address to sign data with - -Returns: -* `signature`: the Cosmos signature derived using signing algorithm `S` - -
- -**cosmosSignTypedPass** - -Params: -* `typedData`: type typed data structure, including the domain separator, to encode and sign +* `data`: the Cosmos signed message canonical JSON structure * `address`: 20 byte account address to sign data with * `password`: password of the account to sign data with @@ -297,6 +178,3 @@ Returns: * `signature`: the Cosmos signature derived using signing algorithm `S` ## References - -1. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md -2. https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign From 6675be23d234442ebaab767a352da03cce0bf166 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Thu, 9 Aug 2018 15:02:50 -0400 Subject: [PATCH 26/97] Add proposed status --- docs/ics/ics-xxx-signed-messages.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 50dd67c75..163763b62 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -10,6 +10,10 @@ * [API](#api) * [References](#references) +## Status + +Proposed. + ## Changelog ## Abstract From 0ab00c8e871b146fa156b60976ae49e607d8c2bd Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 12 Aug 2018 20:10:40 -0400 Subject: [PATCH 27/97] update go-amino dep --- Gopkg.lock | 60 +++++++++++++++++++++++++++--------------------------- Gopkg.toml | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 8fcb2fb5e..808551308 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,11 +34,11 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" + revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" + digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" + digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" + digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,7 +165,7 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -262,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" + digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" + digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" + digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" + digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -347,12 +347,12 @@ revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" [[projects]] - digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" [[projects]] digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" @@ -363,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" + digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:b3cfb8d82b1601a846417c3f31c03a7961862cb2c98dcf0959c473843e6d9a2b" + digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" + digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -407,12 +407,12 @@ revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" [[projects]] - digest = "1:e9113641c839c21d8eaeb2c907c7276af1eddeed988df8322168c56b7e06e0e1" + digest = "1:e0a2a4be1e20c305badc2b0a7a9ab7fef6da500763bec23ab81df3b5f9eec9ee" name = "github.com/tendermint/go-amino" packages = ["."] pruneopts = "UT" - revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" - version = "0.10.1" + revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" + version = "v0.12.0-rc0" [[projects]] digest = "1:d4a15d404afbf591e8be16fcda7f5ac87948d5c7531f9d909fd84cc730ab16e2" @@ -423,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" + digest = "1:df232b6f3c44554161093af004100f75e564b398ad3ff63ecbc297fe400dcfdb" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +498,7 @@ [[projects]] branch = "master" - digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" + digest = "1:3c3c47c1f7587c380afcc1d76385a4a03a2917b9ccc1ac50864d8f87e0264ada" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -517,10 +517,10 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "f027049dab0ad238e394a753dba2d14753473a04" + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" + digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" name = "golang.org/x/net" packages = [ "context", @@ -537,17 +537,17 @@ [[projects]] branch = "master" - digest = "1:4d64ef38a30b73db6e8e7a2824b7fd356d921e0ee3fdd3248658996821d3b47d" + digest = "1:a97b28c54844d6b9848a840ae83d4d263292e831e8c2a586116fcab5c7cfe5f2" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + revision = "98c5dad5d1a0e8a73845ecc8897d0bd56586511d" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" name = "golang.org/x/text" packages = [ "collate", @@ -575,10 +575,10 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" name = "google.golang.org/grpc" packages = [ ".", diff --git a/Gopkg.toml b/Gopkg.toml index 1c7019ae6..e9343195c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -49,7 +49,7 @@ [[override]] name = "github.com/tendermint/go-amino" - version = "=0.10.1" + version = "=v0.12.0-rc0" [[override]] name = "github.com/tendermint/iavl" From 59acfe857fb0a0230917e8fe7ddb27e371274b13 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 12 Aug 2018 20:10:59 -0400 Subject: [PATCH 28/97] WIP: reorg PENDING.md --- PENDING.md | 74 +++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/PENDING.md b/PENDING.md index 4ca3e6df5..1df402d88 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,43 +1,39 @@ ## v0.24.0 PENDING -^--- PENDING wasn't purged on sdk v0.23.0 release. BREAKING CHANGES -* Update to tendermint v0.23.0. This involves removing crypto.Pubkey, -maintaining a validator address to pubkey map, and using time.Time instead of int64 for time. [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) -## PENDING +* Gaia REST API (`gaiacli advanced rest-server`) + - [x/stake] \#1880 More REST-ful endpoints + - [x/slashing] \#1866 `/slashing/signing_info` takes cosmosvalpub instead of cosmosvaladdr + - use time.Time instead of int64 for time. -BREAKING CHANGES -* API - - \#1880 [x/stake] changed the endpoints to be more REST-ful -* Update to tendermint v0.22.5. This involves changing all of the cryptography imports. [Ref](https://github.com/tendermint/tendermint/pull/1966) -* [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` -* [x/gov] CLI flag changed from `proposalID` to `proposal-id` -* [x/stake] Fixed the period check for the inflation calculation -* [x/stake] Inflation doesn't use rationals in calculation (performance boost) -* [x/stake] CLI flags for identity changed from `--keybase-sig` to `--identity`, effects: - * `gaiacli stake create-validator` - * `gaiacli stake edit-validator` -* [baseapp] NewBaseApp constructor now takes sdk.TxDecoder as argument instead of wire.Codec -* [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp -* \#1606 The following CLI commands have been switched to use `--from` - * `gaiacli stake create-validator --address-validator` - * `gaiacli stake edit-validator --address-validator` - * `gaiacli stake delegate --address-delegator` - * `gaiacli stake unbond begin --address-delegator` - * `gaiacli stake unbond complete --address-delegator` - * `gaiacli stake redelegate begin --address-delegator` - * `gaiacli stake redelegate complete --address-delegator` - * `gaiacli stake unrevoke [validator-address]` - * `gaiacli gov submit-proposal --proposer` - * `gaiacli gov deposit --depositer` - * `gaiacli gov vote --voter` -* [x/gov] Added tags sub-package, changed tags to use dash-case -* [x/gov] Governance parameters are now stored in globalparams store -* [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr -* [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 -* [cli] #1551: Officially removed `--name` from CLI commands -* [cli] Genesis/key creation (`init`) now supports user-provided key passwords +* Gaia CLI (`gaiacli`) + - [x/stake] change `--keybase-sig` to `--identity` + - [x/gov] Change `proposalID` to `proposal-id` + - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` + and `--proposer` to indicate the sender address. + - \#1551 Remove `--name` completely + - Genesis/key creation (`gaiad init`) now supports user-provided key passwords + +* Gaia + - [x/stake] Inflation doesn't use rationals in calculation (performance boost) + - [x/stake] Persist a map from `addr->pubkey` in the state since BeginBlock + doesn't provide pubkeys. + - [x/gov] Added tags sub-package, changed tags to use dash-case + - [x/gov] Governance parameters are now stored in globalparams store + +* SDK + - [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` + - [baseapp] NewBaseApp constructor now takes sdk.TxDecoder as argument instead of wire.Codec + - [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 + - [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp + +* Tendermint + - v0.22.5 -> [Tendermint PR](https://github.com/tendermint/tendermint/pull/1966) + - change all the cryptography imports. + - v0.23.0 -> [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) + - BeginBlock no longer includes crypto.Pubkey + - use time.Time instead of int64 for time. FEATURES * [lcd] Can now query governance proposals by ProposalStatus @@ -59,10 +55,8 @@ FEATURES IMPROVEMENTS * [baseapp] Allow any alphanumeric character in route -* [cli] Improve error messages for all txs when the account doesn't exist * [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` * [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly -* [x/stake] Add revoked to human-readable validator * [spec] \#967 Inflation and distribution specs drastically improved * [tests] Add tests to example apps in docs * [x/gov] Votes on a proposal can now be queried @@ -74,9 +68,6 @@ IMPROVEMENTS * [server] \#1930 Transactions indexer indexes all tags by default. BUG FIXES -* \#1666 Add intra-tx counter to the genesis validators -* \#1797 Fix off-by-one error in slashing for downtime -* \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * \#1766 Fixes bad example for keybase identity * \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates * \#1799 Fix `gaiad export` @@ -90,8 +81,5 @@ BUG FIXES structure `TxContext` in `x/auth/client/context` * Cleaned up documentation and API of what used to be `CoreContext` * Implemented `KeyType` enum for key info -* \#1666 Add intra-tx counter to the genesis validators * [tests] \#1551: Fixed invalid LCD test JSON payload in `doIBCTransfer` -* \#1787 Fixed bug where Tally fails due to revoked/unbonding validator -* \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) From a56117ee74a1ac5fb32e0cca63486b1617649838 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 15:41:53 +0200 Subject: [PATCH 29/97] Stage onto release/v0.24.0 (#1999) * Set SignedBlocksWindow back to 1000 * Merge PR #1995: upgrading ledger goclient lib * Update version/version.go --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- version/version.go | 6 +++--- x/slashing/params.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 808551308..1bf3ff1ae 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -490,11 +490,11 @@ version = "v0.23.0" [[projects]] - digest = "1:5bd938386bd1f61a581bf8cd6ff2b7b2f79c542929176db4ceb44965440dae07" + digest = "1:2ea7665579c64cda1873a395de97a2af02df1d06f4cb52128caf57f13249303c" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index e9343195c..a692189e6 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [prune] go-tests = true diff --git a/version/version.go b/version/version.go index 9b332353b..a2bee9eb2 100644 --- a/version/version.go +++ b/version/version.go @@ -2,10 +2,10 @@ package version const Maj = "0" -const Min = "23" -const Fix = "1" +const Min = "24" +const Fix = "0" -const Version = "0.23.1" +const Version = "0.24.0" // GitCommit set by build flags var GitCommit = "" diff --git a/x/slashing/params.go b/x/slashing/params.go index 9d1bc3960..c004ecc52 100644 --- a/x/slashing/params.go +++ b/x/slashing/params.go @@ -66,8 +66,8 @@ var ( // TODO Temporarily set to five minutes for testnets defaultDoubleSignUnbondDuration int64 = 60 * 5 - // TODO Temporarily set to 100 blocks for testnets - defaultSignedBlocksWindow int64 = 100 + // TODO Temporarily set to 1000 blocks for testnets + defaultSignedBlocksWindow int64 = 1000 // TODO Temporarily set to 10 minutes for testnets defaultDowntimeUnbondDuration int64 = 60 * 10 From 0b2bf8f3a0e02844fb959099a27969186ab6fead Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 15:56:40 +0200 Subject: [PATCH 30/97] Set SignedBlocksWindow to 10000 per @zmanian instructions --- x/slashing/params.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/slashing/params.go b/x/slashing/params.go index c004ecc52..2d8102bd6 100644 --- a/x/slashing/params.go +++ b/x/slashing/params.go @@ -66,8 +66,8 @@ var ( // TODO Temporarily set to five minutes for testnets defaultDoubleSignUnbondDuration int64 = 60 * 5 - // TODO Temporarily set to 1000 blocks for testnets - defaultSignedBlocksWindow int64 = 1000 + // TODO Temporarily set to 10000 blocks for testnets + defaultSignedBlocksWindow int64 = 10000 // TODO Temporarily set to 10 minutes for testnets defaultDowntimeUnbondDuration int64 = 60 * 10 From d3322052db2d4e78e956ca77b10a971146369191 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Aug 2018 10:42:47 -0400 Subject: [PATCH 31/97] update pending.md --- PENDING.md | 120 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/PENDING.md b/PENDING.md index 1df402d88..f3c89f044 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,15 +1,22 @@ ## v0.24.0 PENDING +* Gaia REST API (`gaiacli advanced rest-server`) +* Gaia CLI (`gaiacli`) +* Gaia +* SDK +* Tendermint + BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) - - [x/stake] \#1880 More REST-ful endpoints + - [x/stake] \#1880 More REST-ful endpoints (large refactor) - [x/slashing] \#1866 `/slashing/signing_info` takes cosmosvalpub instead of cosmosvaladdr - use time.Time instead of int64 for time. * Gaia CLI (`gaiacli`) - [x/stake] change `--keybase-sig` to `--identity` - - [x/gov] Change `proposalID` to `proposal-id` + - [x/stake] \#1828 Force user to specify amount on create-validator command by removing default + - [x/gov] Change `--proposalID` to `--proposal-id` - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` and `--proposer` to indicate the sender address. - \#1551 Remove `--name` completely @@ -19,14 +26,19 @@ BREAKING CHANGES - [x/stake] Inflation doesn't use rationals in calculation (performance boost) - [x/stake] Persist a map from `addr->pubkey` in the state since BeginBlock doesn't provide pubkeys. - - [x/gov] Added tags sub-package, changed tags to use dash-case - - [x/gov] Governance parameters are now stored in globalparams store + - [x/gov] \#1781 Added tags sub-package, changed tags to use dash-case + - [x/gov] \#1688 Governance parameters are now stored in globalparams store + - [x/gov] \#1859 Slash validators who do not vote on a proposal + - [x/gov] \#1914 added TallyResult type that gets stored in Proposal after tallying is finished * SDK - [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` - - [baseapp] NewBaseApp constructor now takes sdk.TxDecoder as argument instead of wire.Codec - - [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 + - [baseapp] NewBaseApp constructor takes sdk.TxDecoder as argument instead of wire.Codec + - [types] sdk.NewCoin takes sdk.Int, sdk.NewInt64Coin takes int64 - [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp + - [client] \#1551: Refactored `CoreContext` to `TxContext` and `QueryContext` + - Removed all tx related fields and logic (building & signing) to separate + structure `TxContext` in `x/auth/client/context` * Tendermint - v0.22.5 -> [Tendermint PR](https://github.com/tendermint/tendermint/pull/1966) @@ -36,50 +48,60 @@ BREAKING CHANGES - use time.Time instead of int64 for time. FEATURES -* [lcd] Can now query governance proposals by ProposalStatus -* [x/mock/simulation] Randomized simulation framework - * Modules specify invariants and operations, preferably in an x/[module]/simulation package - * Modules can test random combinations of their own operations - * Applications can integrate operations and invariants from modules together for an integrated simulation -* [baseapp] Initialize validator set on ResponseInitChain -* [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd - * This allows SDK users to initialize a new project repository. -* [tests] Remotenet commands for AWS (awsnet) -* [networks] Added ansible scripts to upgrade seed nodes on a network -* [store] Add transient store -* [gov] Add slashing for validators who do not vote on a proposal -* [cli] added `gov query-proposals` command to CLI. Can filter by `depositer`, `voter`, and `status` -* [core] added BaseApp.Seal - ability to seal baseapp parameters once they've been set -* [scripts] added log output monitoring to DataDog using Ansible scripts -* [gov] added TallyResult type that gets added stored in Proposal after tallying is finished + +* Gaia REST API (`gaiacli advanced rest-server`) + - [x/gov] Can now query governance proposals by ProposalStatus + +* Gaia CLI (`gaiacli`) + - [x/gov] added `query-proposals` command. Can filter by `depositer`, `voter`, and `status` + +* Gaia + - [networks] Added ansible scripts to upgrade seed nodes on a network + +* SDK + - [x/mock/simulation] Randomized simulation framework + - Modules specify invariants and operations, preferably in an x/[module]/simulation package + - Modules can test random combinations of their own operations + - Applications can integrate operations and invariants from modules together for an integrated simulation + - [store] \#1481 Add transient store + - [baseapp] Initialize validator set on ResponseInitChain + - [baseapp] added BaseApp.Seal - ability to seal baseapp parameters once they've been set + - [cosmos-sdk-cli] New `cosmos-sdk-cli` tool to quickly initialize a new + SDK-based project + - [scripts] added log output monitoring to DataDog using Ansible scripts IMPROVEMENTS -* [baseapp] Allow any alphanumeric character in route -* [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` -* [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly -* [spec] \#967 Inflation and distribution specs drastically improved -* [tests] Add tests to example apps in docs -* [x/gov] Votes on a proposal can now be queried -* [x/bank] Unit tests are now table-driven -* [tests] Fixes ansible scripts to work with AWS too -* [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo -* [x/gov] Initial governance parameters can now be set in the genesis file -* [x/stake] \#1815 Sped up the processing of `EditValidator` txs. -* [server] \#1930 Transactions indexer indexes all tags by default. + +* Gaia + - [spec] \#967 Inflation and distribution specs drastically improved + - [x/gov] \#1773 Votes on a proposal can now be queried + - [x/gov] Initial governance parameters can now be set in the genesis file + - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. + - [config] \#1930 Transactions indexer indexes all tags by default. + +* SDK + - [baseapp] \#1587 Allow any alphanumeric character in route + - [baseapp] Allow any alphanumeric character in route + - [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` + - [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly + - [x/bank] Unit tests are now table-driven + - [tests] Add tests to example apps in docs + - [tests] Fixes ansible scripts to work with AWS too + - [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo BUG FIXES -* \#1766 Fixes bad example for keybase identity -* \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates -* \#1799 Fix `gaiad export` -* \#1828 Force user to specify amount on create-validator command by removing default -* \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators -* [staking] [#1858](https://github.com/cosmos/cosmos-sdk/pull/1858) Fixed bug where the cliff validator was not be updated correctly -* [tests] \#1675 Fix non-deterministic `test_cover` -* [client] \#1551: Refactored `CoreContext` - * Renamed `CoreContext` to `QueryContext` - * Removed all tx related fields and logic (building & signing) to separate - structure `TxContext` in `x/auth/client/context` - * Cleaned up documentation and API of what used to be `CoreContext` - * Implemented `KeyType` enum for key info -* [tests] \#1551: Fixed invalid LCD test JSON payload in `doIBCTransfer` -* [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) + +* Gaia CLI (`gaiacli`) + - \#1766 Fixes bad example for keybase identity + +* Gaia + - \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates + - \#1799 Fix `gaiad export` + - \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators + - [x/stake] \#1858 Fixed bug where the cliff validator was not updated correctly + - [tests] \#1675 Fix non-deterministic `test_cover` + - [tests] \#1551 Fixed invalid LCD test JSON payload in `doIBCTransfer` + - [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) + - [x/gov] \#1757 Fix VoteOption conversion to String + + From e64a5538e41e9dee661deb8e88ddd94f1a5faa68 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Aug 2018 10:47:44 -0400 Subject: [PATCH 32/97] update changelog, reset pending --- CHANGELOG.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ PENDING.md | 88 +++++++++++------------------------------- 2 files changed, 129 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d8864201..7b6103526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,112 @@ # Changelog +## 0.24.0 + +*August 13th, 2018* + +BREAKING CHANGES + +* Gaia REST API (`gaiacli advanced rest-server`) + - [x/stake] \#1880 More REST-ful endpoints (large refactor) + - [x/slashing] \#1866 `/slashing/signing_info` takes cosmosvalpub instead of cosmosvaladdr + - use time.Time instead of int64 for time. See Tendermint v0.23.0 + - Signatures are no longer Amino encoded with prefixes (just encoded as raw + bytes) - see Tendermint v0.23.0 + +* Gaia CLI (`gaiacli`) + - [x/stake] change `--keybase-sig` to `--identity` + - [x/stake] \#1828 Force user to specify amount on create-validator command by removing default + - [x/gov] Change `--proposalID` to `--proposal-id` + - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` + and `--proposer` to indicate the sender address. + - \#1551 Remove `--name` completely + - Genesis/key creation (`gaiad init`) now supports user-provided key passwords + +* Gaia + - [x/stake] Inflation doesn't use rationals in calculation (performance boost) + - [x/stake] Persist a map from `addr->pubkey` in the state since BeginBlock + doesn't provide pubkeys. + - [x/gov] \#1781 Added tags sub-package, changed tags to use dash-case + - [x/gov] \#1688 Governance parameters are now stored in globalparams store + - [x/gov] \#1859 Slash validators who do not vote on a proposal + - [x/gov] \#1914 added TallyResult type that gets stored in Proposal after tallying is finished + +* SDK + - [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` + - [baseapp] NewBaseApp constructor takes sdk.TxDecoder as argument instead of wire.Codec + - [types] sdk.NewCoin takes sdk.Int, sdk.NewInt64Coin takes int64 + - [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp + - [client] \#1551: Refactored `CoreContext` to `TxContext` and `QueryContext` + - Removed all tx related fields and logic (building & signing) to separate + structure `TxContext` in `x/auth/client/context` + +* Tendermint + - v0.22.5 -> See [Tendermint PR](https://github.com/tendermint/tendermint/pull/1966) + - change all the cryptography imports. + - v0.23.0 -> See + [Changelog](https://github.com/tendermint/tendermint/blob/v0.23.0/CHANGELOG.md#0230) + and [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) + - BeginBlock no longer includes crypto.Pubkey + - use time.Time instead of int64 for time. + +FEATURES + +* Gaia REST API (`gaiacli advanced rest-server`) + - [x/gov] Can now query governance proposals by ProposalStatus + +* Gaia CLI (`gaiacli`) + - [x/gov] added `query-proposals` command. Can filter by `depositer`, `voter`, and `status` + +* Gaia + - [networks] Added ansible scripts to upgrade seed nodes on a network + +* SDK + - [x/mock/simulation] Randomized simulation framework + - Modules specify invariants and operations, preferably in an x/[module]/simulation package + - Modules can test random combinations of their own operations + - Applications can integrate operations and invariants from modules together for an integrated simulation + - [store] \#1481 Add transient store + - [baseapp] Initialize validator set on ResponseInitChain + - [baseapp] added BaseApp.Seal - ability to seal baseapp parameters once they've been set + - [cosmos-sdk-cli] New `cosmos-sdk-cli` tool to quickly initialize a new + SDK-based project + - [scripts] added log output monitoring to DataDog using Ansible scripts + +IMPROVEMENTS + +* Gaia + - [spec] \#967 Inflation and distribution specs drastically improved + - [x/gov] \#1773 Votes on a proposal can now be queried + - [x/gov] Initial governance parameters can now be set in the genesis file + - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. + - [config] \#1930 Transactions indexer indexes all tags by default. + +* SDK + - [baseapp] \#1587 Allow any alphanumeric character in route + - [baseapp] Allow any alphanumeric character in route + - [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` + - [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly + - [x/bank] Unit tests are now table-driven + - [tests] Add tests to example apps in docs + - [tests] Fixes ansible scripts to work with AWS too + - [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo + +BUG FIXES + +* Gaia CLI (`gaiacli`) + - \#1766 Fixes bad example for keybase identity + +* Gaia + - \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates + - \#1799 Fix `gaiad export` + - \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators + - [x/stake] \#1858 Fixed bug where the cliff validator was not updated correctly + - [tests] \#1675 Fix non-deterministic `test_cover` + - [tests] \#1551 Fixed invalid LCD test JSON payload in `doIBCTransfer` + - [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) + - [x/gov] \#1757 Fix VoteOption conversion to String + + ## 0.23.1 *July 27th, 2018* diff --git a/PENDING.md b/PENDING.md index f3c89f044..5d0e7dba0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,107 +1,63 @@ -## v0.24.0 PENDING +## PENDING * Gaia REST API (`gaiacli advanced rest-server`) + * Gaia CLI (`gaiacli`) + * Gaia + * SDK + * Tendermint BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) - - [x/stake] \#1880 More REST-ful endpoints (large refactor) - - [x/slashing] \#1866 `/slashing/signing_info` takes cosmosvalpub instead of cosmosvaladdr - - use time.Time instead of int64 for time. * Gaia CLI (`gaiacli`) - - [x/stake] change `--keybase-sig` to `--identity` - - [x/stake] \#1828 Force user to specify amount on create-validator command by removing default - - [x/gov] Change `--proposalID` to `--proposal-id` - - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` - and `--proposer` to indicate the sender address. - - \#1551 Remove `--name` completely - - Genesis/key creation (`gaiad init`) now supports user-provided key passwords * Gaia - - [x/stake] Inflation doesn't use rationals in calculation (performance boost) - - [x/stake] Persist a map from `addr->pubkey` in the state since BeginBlock - doesn't provide pubkeys. - - [x/gov] \#1781 Added tags sub-package, changed tags to use dash-case - - [x/gov] \#1688 Governance parameters are now stored in globalparams store - - [x/gov] \#1859 Slash validators who do not vote on a proposal - - [x/gov] \#1914 added TallyResult type that gets stored in Proposal after tallying is finished - + * SDK - - [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` - - [baseapp] NewBaseApp constructor takes sdk.TxDecoder as argument instead of wire.Codec - - [types] sdk.NewCoin takes sdk.Int, sdk.NewInt64Coin takes int64 - - [x/auth] Default TxDecoder can be found in `x/auth` rather than baseapp - - [client] \#1551: Refactored `CoreContext` to `TxContext` and `QueryContext` - - Removed all tx related fields and logic (building & signing) to separate - structure `TxContext` in `x/auth/client/context` * Tendermint - - v0.22.5 -> [Tendermint PR](https://github.com/tendermint/tendermint/pull/1966) - - change all the cryptography imports. - - v0.23.0 -> [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) - - BeginBlock no longer includes crypto.Pubkey - - use time.Time instead of int64 for time. + FEATURES * Gaia REST API (`gaiacli advanced rest-server`) - - [x/gov] Can now query governance proposals by ProposalStatus * Gaia CLI (`gaiacli`) - - [x/gov] added `query-proposals` command. Can filter by `depositer`, `voter`, and `status` * Gaia - - [networks] Added ansible scripts to upgrade seed nodes on a network * SDK - - [x/mock/simulation] Randomized simulation framework - - Modules specify invariants and operations, preferably in an x/[module]/simulation package - - Modules can test random combinations of their own operations - - Applications can integrate operations and invariants from modules together for an integrated simulation - - [store] \#1481 Add transient store - - [baseapp] Initialize validator set on ResponseInitChain - - [baseapp] added BaseApp.Seal - ability to seal baseapp parameters once they've been set - - [cosmos-sdk-cli] New `cosmos-sdk-cli` tool to quickly initialize a new - SDK-based project - - [scripts] added log output monitoring to DataDog using Ansible scripts + +* Tendermint + IMPROVEMENTS +* Gaia REST API (`gaiacli advanced rest-server`) + +* Gaia CLI (`gaiacli`) + * Gaia - - [spec] \#967 Inflation and distribution specs drastically improved - - [x/gov] \#1773 Votes on a proposal can now be queried - - [x/gov] Initial governance parameters can now be set in the genesis file - - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. - - [config] \#1930 Transactions indexer indexes all tags by default. * SDK - - [baseapp] \#1587 Allow any alphanumeric character in route - - [baseapp] Allow any alphanumeric character in route - - [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` - - [x/auth] Recover ErrorOutOfGas panic in order to set sdk.Result attributes correctly - - [x/bank] Unit tests are now table-driven - - [tests] Add tests to example apps in docs - - [tests] Fixes ansible scripts to work with AWS too - - [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo + +* Tendermint + BUG FIXES +* Gaia REST API (`gaiacli advanced rest-server`) + * Gaia CLI (`gaiacli`) - - \#1766 Fixes bad example for keybase identity * Gaia - - \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates - - \#1799 Fix `gaiad export` - - \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators - - [x/stake] \#1858 Fixed bug where the cliff validator was not updated correctly - - [tests] \#1675 Fix non-deterministic `test_cover` - - [tests] \#1551 Fixed invalid LCD test JSON payload in `doIBCTransfer` - - [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) - - [x/gov] \#1757 Fix VoteOption conversion to String +* SDK + +* Tendermint From 1cb89b958b41f24d9da556eccadea4f0d0c065cb Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Mon, 13 Aug 2018 11:14:01 -0400 Subject: [PATCH 33/97] update pending --- PENDING.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/PENDING.md b/PENDING.md index 5d0e7dba0..cba76aae6 100644 --- a/PENDING.md +++ b/PENDING.md @@ -1,15 +1,5 @@ ## PENDING -* Gaia REST API (`gaiacli advanced rest-server`) - -* Gaia CLI (`gaiacli`) - -* Gaia - -* SDK - -* Tendermint - BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) From 61b49d560f473f44f93dd5fdf96b6e39d6de0806 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Mon, 13 Aug 2018 18:15:55 +0200 Subject: [PATCH 34/97] Merge PR #2003: Update upstream Ledger Go client --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 1bf3ff1ae..cc42ac4f4 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -490,11 +490,11 @@ version = "v0.23.0" [[projects]] - digest = "1:2ea7665579c64cda1873a395de97a2af02df1d06f4cb52128caf57f13249303c" + digest = "1:4dcb0dd65feecb068ce23a234d1a07c7868a1e39f52a6defcae0bb371d03abf6" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "a05312e1c998ad831b70eea41d009654f7f95985" + revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index a692189e6..acc3e282a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "a05312e1c998ad831b70eea41d009654f7f95985" + revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [prune] go-tests = true From c9cbb0b09458c708a34d2fcbc4d40db19340024c Mon Sep 17 00:00:00 2001 From: Jack Zampolin Date: Mon, 13 Aug 2018 12:41:07 -0700 Subject: [PATCH 35/97] Merge PR #2010: Add RELEASE_TEST_SCRIPT.md --- cmd/gaia/testnets/gaia-5001/adrian.json | 20 - cmd/gaia/testnets/gaia-5001/anton.json | 20 - cmd/gaia/testnets/gaia-5001/aurel.json | 20 - cmd/gaia/testnets/gaia-5001/bucky.json | 20 - cmd/gaia/testnets/gaia-5001/cwgoes.json | 20 - cmd/gaia/testnets/gaia-5001/iris.json | 20 - cmd/gaia/testnets/gaia-5001/lino.json | 20 - cmd/gaia/testnets/gaia-5001/pbostrom.json | 20 - cmd/gaia/testnets/gaia-5001/poldsam.json | 20 - cmd/gaia/testnets/gaia-5001/staked.json | 20 - cmd/gaia/testnets/gaia-5001/zach.json | 20 - cmd/gaia/testnets/gaia-5001/zaki.json | 20 - cmd/gaia/testnets/gaia-6000/genesis.json | 1459 ------ cmd/gaia/testnets/gaia-6001/genesis.json | 1459 ------ cmd/gaia/testnets/gaia-6002/genesis.json | 1459 ------ cmd/gaia/testnets/gaia-7000/genesis.json | 5680 --------------------- cmd/gaia/testnets/gaia-7001/genesis.json | 5628 -------------------- docs/RELEASE_PROCESS.md | 2 +- docs/RELEASE_TEST_SCRIPT.md | 17 + docs/getting-started/create-testnet.md | 27 + docs/sdk/clients.md | 2 +- docs/validators/validator-setup.md | 129 + 22 files changed, 175 insertions(+), 15927 deletions(-) delete mode 100644 cmd/gaia/testnets/gaia-5001/adrian.json delete mode 100644 cmd/gaia/testnets/gaia-5001/anton.json delete mode 100644 cmd/gaia/testnets/gaia-5001/aurel.json delete mode 100644 cmd/gaia/testnets/gaia-5001/bucky.json delete mode 100644 cmd/gaia/testnets/gaia-5001/cwgoes.json delete mode 100644 cmd/gaia/testnets/gaia-5001/iris.json delete mode 100644 cmd/gaia/testnets/gaia-5001/lino.json delete mode 100644 cmd/gaia/testnets/gaia-5001/pbostrom.json delete mode 100644 cmd/gaia/testnets/gaia-5001/poldsam.json delete mode 100644 cmd/gaia/testnets/gaia-5001/staked.json delete mode 100644 cmd/gaia/testnets/gaia-5001/zach.json delete mode 100644 cmd/gaia/testnets/gaia-5001/zaki.json delete mode 100644 cmd/gaia/testnets/gaia-6000/genesis.json delete mode 100644 cmd/gaia/testnets/gaia-6001/genesis.json delete mode 100644 cmd/gaia/testnets/gaia-6002/genesis.json delete mode 100644 cmd/gaia/testnets/gaia-7000/genesis.json delete mode 100644 cmd/gaia/testnets/gaia-7001/genesis.json create mode 100644 docs/RELEASE_TEST_SCRIPT.md create mode 100644 docs/getting-started/create-testnet.md diff --git a/cmd/gaia/testnets/gaia-5001/adrian.json b/cmd/gaia/testnets/gaia-5001/adrian.json deleted file mode 100644 index 7ca99cb1e..000000000 --- a/cmd/gaia/testnets/gaia-5001/adrian.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "1ebc5ca705b3ae1c06a0888ff1287ada82149dc3", - "ip": "138.68.77.24", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "power": 100, - "name": "adrian" - }, - "app_gen_tx": { - "name": "default", - "address": "D9C12CB5186FE0018179742FD3110EE534C63460", - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/anton.json b/cmd/gaia/testnets/gaia-5001/anton.json deleted file mode 100644 index 701e85887..000000000 --- a/cmd/gaia/testnets/gaia-5001/anton.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "c272ae3cff7558db2c6195eea38fd43fd08406dc", - "ip": "206.189.31.178", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "tJlZJWjOpYvRitYFTWNPTaUtvQVf+hoNjlfI84VPqvI=" - }, - "power": 100, - "name": "anton" - }, - "app_gen_tx": { - "name": "default", - "address": "E766088FD171906289617F60BF0014C46F0F85EC", - "pub_key": { - "type": "AC26791624DE60", - "value": "tJlZJWjOpYvRitYFTWNPTaUtvQVf+hoNjlfI84VPqvI=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/aurel.json b/cmd/gaia/testnets/gaia-5001/aurel.json deleted file mode 100644 index 0c2ea8166..000000000 --- a/cmd/gaia/testnets/gaia-5001/aurel.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "aef085c4bfed0c1ffc6705f2e1e3bf85e5164600", - "ip": "45.77.53.208", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "power": 100, - "name": "aurel" - }, - "app_gen_tx": { - "name": "aurel", - "address": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/bucky.json b/cmd/gaia/testnets/gaia-5001/bucky.json deleted file mode 100644 index fc4bb51cd..000000000 --- a/cmd/gaia/testnets/gaia-5001/bucky.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "b0dd378c3fbc4c156cd6d302a799f0d2e4227201", - "ip": "159.89.121.174", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "power": 100, - "name": "bucky" - }, - "app_gen_tx": { - "name": "bucky", - "address": "935E48ED79F1006ED135553768E1D9A768747CF6", - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/cwgoes.json b/cmd/gaia/testnets/gaia-5001/cwgoes.json deleted file mode 100644 index dce7e20c9..000000000 --- a/cmd/gaia/testnets/gaia-5001/cwgoes.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "e25603602d8cf8542570ad0e311d50f55f497f85", - "ip": "158.69.63.13", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "power": 100, - "name": "cwgoes" - }, - "app_gen_tx": { - "name": "cwgoes", - "address": "328FBB8EA315D070DF908982A5F91A3618001D20", - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/iris.json b/cmd/gaia/testnets/gaia-5001/iris.json deleted file mode 100644 index 1a1019672..000000000 --- a/cmd/gaia/testnets/gaia-5001/iris.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "aabf05a67b2f399807dc602d05bf97b0ed283ac2", - "ip": "116.62.62.39", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "power": 100, - "name": "iris" - }, - "app_gen_tx": { - "name": "=suyu", - "address": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - } - } -} \ No newline at end of file diff --git a/cmd/gaia/testnets/gaia-5001/lino.json b/cmd/gaia/testnets/gaia-5001/lino.json deleted file mode 100644 index 5bc98bb6e..000000000 --- a/cmd/gaia/testnets/gaia-5001/lino.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "79466a03e9d4b4648a7dd8cead1fa7121ce76ee3", - "ip": "34.235.130.1", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "power": 100, - "name": "lino" - }, - "app_gen_tx": { - "name": "lino", - "address": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/pbostrom.json b/cmd/gaia/testnets/gaia-5001/pbostrom.json deleted file mode 100644 index 59cd46950..000000000 --- a/cmd/gaia/testnets/gaia-5001/pbostrom.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "adb290585a2753bf1a520c76802b0dab3dffa895", - "ip": "34.201.21.179", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "power": 100, - "name": "pbostrom" - }, - "app_gen_tx": { - "name": "default", - "address": "109720515B4F8C0858DA3521E448262334534FFD", - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/poldsam.json b/cmd/gaia/testnets/gaia-5001/poldsam.json deleted file mode 100644 index 8149a9259..000000000 --- a/cmd/gaia/testnets/gaia-5001/poldsam.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "678503e6c8f50db7279c7da3cb9b072aac4bc0d5", - "ip": "35.193.188.125", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "power": 100, - "name": "polsdam" - }, - "app_gen_tx": { - "name": "poldsam", - "address": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/staked.json b/cmd/gaia/testnets/gaia-5001/staked.json deleted file mode 100644 index f39cced6b..000000000 --- a/cmd/gaia/testnets/gaia-5001/staked.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "3519f05985394107e0b2e285361b7e012adb1113", - "ip": "54.209.118.64", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "vq0V0BjpmIh6WyNnFpMaO5LyUK2FamkNt65eJYa5AaQ=" - }, - "power": 100, - "name": "staked" - }, - "app_gen_tx": { - "name": "default", - "address": "935E04662697134905706A4CCDB822AC6FC11C2E", - "pub_key": { - "type": "AC26791624DE60", - "value": "vq0V0BjpmIh6WyNnFpMaO5LyUK2FamkNt65eJYa5AaQ=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/zach.json b/cmd/gaia/testnets/gaia-5001/zach.json deleted file mode 100644 index 76a08cc92..000000000 --- a/cmd/gaia/testnets/gaia-5001/zach.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "8a2802fb25d352f3e7e277559a4f683780c3ef22", - "ip": "167.99.191.184", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "power": 100, - "name": "" - }, - "app_gen_tx": { - "name": "zach", - "address": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-5001/zaki.json b/cmd/gaia/testnets/gaia-5001/zaki.json deleted file mode 100644 index 956f2bf8c..000000000 --- a/cmd/gaia/testnets/gaia-5001/zaki.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node_id": "30b45459e4881680c0ef1750fde136fefa6c3b98", - "ip": "35.184.182.143", - "validator": { - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "power": 100, - "name": "zaki" - }, - "app_gen_tx": { - "name": "zaki", - "address": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - } - } -} diff --git a/cmd/gaia/testnets/gaia-6000/genesis.json b/cmd/gaia/testnets/gaia-6000/genesis.json deleted file mode 100644 index aefab9286..000000000 --- a/cmd/gaia/testnets/gaia-6000/genesis.json +++ /dev/null @@ -1,1459 +0,0 @@ -{ - "genesis_time": "2018-05-15T18:29:12.38288148Z", - "chain_id": "gaia-6000", - "consensus_params": { - "block_size_params": { - "max_bytes": 22020096, - "max_txs": 100000, - "max_gas": -1 - }, - "tx_size_params": { - "max_bytes": 10240, - "max_gas": -1 - }, - "block_gossip_params": { - "block_part_size_bytes": 65536 - }, - "evidence_params": { - "max_age": 100000 - } - }, - "validators": [ - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "power": 1000, - "name": "adrian" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "power": 1000, - "name": "zaki" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "power": 100, - "name": "staked" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "power": 1000, - "name": "polsdam" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "power": 1000, - "name": "lino" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "power": 100, - "name": "" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "power": 1000, - "name": "iris" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "power": 1000, - "name": "pbostrom" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "power": 1000, - "name": "aurel" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "power": 1000, - "name": "bucky" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "power": 100, - "name": "cwgoes" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "power": 1000, - "name": "bdnet" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "power": 1000, - "name": "melea-trust" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "power": 1000, - "name": "naruemon" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "power": 1000, - "name": "idoor" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "power": 1000, - "name": "ATEAM1" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "power": 1000, - "name": "figmatt" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "power": 1000, - "name": "jla-bsd" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "power": 1000, - "name": "Gold" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "power": 1000, - "name": "nylira" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "power": 1000, - "name": "BKCM" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "power": 1000, - "name": "Dev's Validator" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "power": 1000, - "name": "Staking Facilities" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "power": 1000, - "name": "nuevax" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "power": 1000, - "name": "vultr.guest" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "power": 1000, - "name": "forebole" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "coins": [ - { - "denom": "devToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "coins": [ - { - "denom": "adrianToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "109720515B4F8C0858DA3521E448262334534FFD", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "coins": [ - { - "denom": "aurelToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "328FBB8EA315D070DF908982A5F91A3618001D20", - "coins": [ - { - "denom": "cwgoesToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "coins": [ - { - "denom": "BKCMToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "coins": [ - { - "denom": "BDToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "coins": [ - { - "denom": "suyuToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "coins": [ - { - "denom": "linoToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "coins": [ - { - "denom": "stakingToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E04662697134905706A4CCDB822AC6FC11C2E", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E48ED79F1006ED135553768E1D9A768747CF6", - "coins": [ - { - "denom": "buckyToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "99FFAEE5BF6040EADA2F26548C4A702619797C9F", - "coins": [ - { - "denom": "kwunyeungToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zachToken", - "amount": 1000 - } - ] - }, - { - "address": "A323EC45243D600204BA3D298E3C20322D08C84C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "nuevaxToken", - "amount": 1000 - } - ] - }, - { - "address": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "dokiaToken", - "amount": 1000 - } - ] - }, - { - "address": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "forboleToken", - "amount": 1000 - } - ] - }, - { - "address": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "coins": [ - { - "denom": "steak", - "amount": 100 - }, - { - "denom": "pengToken", - "amount": 1000 - } - ] - }, - { - "address": "FD30D5C983FFEDEC069C3DDFCF270E41A556A86E", - "coins": [ - { - "denom": "steak", - "amount": 900 - }, - { - "denom": "faucetToken", - "amount": 10000000 - } - ] - }, - { - "address": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "goldToken", - "amount": 100 - } - ] - }, - { - "address": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "jlaToken", - "amount": 100 - } - ] - }, - { - "address": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "figmattToken", - "amount": 100 - } - ] - }, - { - "address": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "ATEAM1Token", - "amount": 100 - } - ] - }, - { - "address": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "idoorToken", - "amount": 100 - } - ] - }, - { - "address": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "naruemonToken", - "amount": 100 - } - ] - }, - { - "address": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zakiToken", - "amount": 1000 - } - ] - }, - { - "address": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "trustToken", - "amount": 1000 - } - ] - }, - { - "address": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "coins": [ - { - "denom": "poldsamToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - } - ], - "stake": { - "pool": { - "loose_unbonded_tokens": 2350, - "unbonded_tokens": 0, - "unbonding_tokens": 0, - "bonded_tokens": 25200, - "unbonded_shares": "0", - "unbonding_shares": "0", - "bonded_shares": "25200", - "inflation_last_time": 0, - "inflation": "9012837/100000000", - "date_last_commission_reset": 0, - "prev_bonded_shares": "0" - }, - "params": { - "inflation_rate_change": "13/100", - "inflation_max": "1/5", - "inflation_min": "7/100", - "goal_bonded": "67/100", - "max_validators": 100, - "bond_denom": "steak" - }, - "bonds": [ - { - "delegator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "validator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "validator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "validator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "validator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "validator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "validator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "validator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "validator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "validator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "validator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "validator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "validator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "validator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "validator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "validator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "validator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "validator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "validator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "validator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "validator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "validator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "validator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "validator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "validator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "validator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "validator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "shares": "1000", - "height": 0 - } - ], - "validators": [ - { - "owner": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "description": { - "moniker": "Dev's Validator", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "109720515B4F8C0858DA3521E448262334534FFD", - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "description": { - "moniker": "", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "description": { - "moniker": "aurel", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "328FBB8EA315D070DF908982A5F91A3618001D20", - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "description": { - "moniker": "cwgoes", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "description": { - "moniker": "BKCM", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "description": { - "moniker": "bdnet", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "description": { - "moniker": "suyu", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "description": { - "moniker": "lino", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "description": { - "moniker": "Staking Facilities", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E04662697134905706A4CCDB822AC6FC11C2E", - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "description": { - "moniker": "default", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E48ED79F1006ED135553768E1D9A768747CF6", - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "description": { - "moniker": "bucky", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "description": { - "moniker": "zach", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A323EC45243D600204BA3D298E3C20322D08C84C", - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "description": { - "moniker": "nuevax", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "description": { - "moniker": "vultr.guest", - "identity": "", - "website": "https://ion.dokia.capital/", - "details": "DokiaValidator" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "description": { - "moniker": "forbole", - "identity": "", - "website": "https://www.forbole.com", - "details": "Recommend. Refer. Reward" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "description": { - "moniker": "nylira", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "description": { - "moniker": "Gold", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "description": { - "moniker": "jla-bsd", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "description": { - "moniker": "figmatt", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "description": { - "moniker": "ATEAM1", - "identity": "", - "website": "", - "details": "ATEAM1" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "description": { - "moniker": "idoor", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "description": { - "moniker": "naruemon", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "description": { - "moniker": "Adrian Brink - Cryptium Labs", - "identity": "", - "website": "https://cryptium.ch", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "description": { - "moniker": "zaki", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "description": { - "moniker": "trust", - "identity": "", - "website": "http://cosmos-trust.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "description": { - "moniker": "proof-of-audit", - "identity": "", - "website": "https://proof-of-audit.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - } - ] - } - } -} diff --git a/cmd/gaia/testnets/gaia-6001/genesis.json b/cmd/gaia/testnets/gaia-6001/genesis.json deleted file mode 100644 index 512d761be..000000000 --- a/cmd/gaia/testnets/gaia-6001/genesis.json +++ /dev/null @@ -1,1459 +0,0 @@ -{ - "genesis_time": "2018-05-15T18:29:12.38288148Z", - "chain_id": "gaia-6001", - "consensus_params": { - "block_size_params": { - "max_bytes": 22020096, - "max_txs": 100000, - "max_gas": -1 - }, - "tx_size_params": { - "max_bytes": 10240, - "max_gas": -1 - }, - "block_gossip_params": { - "block_part_size_bytes": 65536 - }, - "evidence_params": { - "max_age": 100000 - } - }, - "validators": [ - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "power": 1000, - "name": "adrian" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "power": 1000, - "name": "zaki" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "power": 100, - "name": "staked" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "power": 1000, - "name": "polsdam" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "power": 1000, - "name": "lino" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "power": 100, - "name": "" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "power": 1000, - "name": "iris" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "power": 1000, - "name": "pbostrom" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "power": 1000, - "name": "aurel" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "power": 1000, - "name": "bucky" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "power": 100, - "name": "cwgoes" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "power": 1000, - "name": "bdnet" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "power": 1000, - "name": "melea-trust" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "power": 1000, - "name": "naruemon" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "power": 1000, - "name": "idoor" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "power": 1000, - "name": "ATEAM1" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "power": 1000, - "name": "figmatt" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "power": 1000, - "name": "jla-bsd" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "power": 1000, - "name": "Gold" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "power": 1000, - "name": "nylira" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "power": 1000, - "name": "BKCM" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "power": 1000, - "name": "Dev's Validator" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "power": 1000, - "name": "Staking Facilities" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "power": 1000, - "name": "nuevax" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "power": 1000, - "name": "vultr.guest" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "power": 1000, - "name": "forebole" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "coins": [ - { - "denom": "devToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "coins": [ - { - "denom": "adrianToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "109720515B4F8C0858DA3521E448262334534FFD", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "coins": [ - { - "denom": "aurelToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "328FBB8EA315D070DF908982A5F91A3618001D20", - "coins": [ - { - "denom": "cwgoesToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "coins": [ - { - "denom": "BKCMToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "coins": [ - { - "denom": "BDToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "coins": [ - { - "denom": "suyuToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "coins": [ - { - "denom": "linoToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "coins": [ - { - "denom": "stakingToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E04662697134905706A4CCDB822AC6FC11C2E", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E48ED79F1006ED135553768E1D9A768747CF6", - "coins": [ - { - "denom": "buckyToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "99FFAEE5BF6040EADA2F26548C4A702619797C9F", - "coins": [ - { - "denom": "kwunyeungToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zachToken", - "amount": 1000 - } - ] - }, - { - "address": "A323EC45243D600204BA3D298E3C20322D08C84C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "nuevaxToken", - "amount": 1000 - } - ] - }, - { - "address": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "dokiaToken", - "amount": 1000 - } - ] - }, - { - "address": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "forboleToken", - "amount": 1000 - } - ] - }, - { - "address": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "coins": [ - { - "denom": "steak", - "amount": 100 - }, - { - "denom": "pengToken", - "amount": 1000 - } - ] - }, - { - "address": "FD30D5C983FFEDEC069C3DDFCF270E41A556A86E", - "coins": [ - { - "denom": "steak", - "amount": 900 - }, - { - "denom": "faucetToken", - "amount": 10000000 - } - ] - }, - { - "address": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "goldToken", - "amount": 100 - } - ] - }, - { - "address": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "jlaToken", - "amount": 100 - } - ] - }, - { - "address": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "figmattToken", - "amount": 100 - } - ] - }, - { - "address": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "ATEAM1Token", - "amount": 100 - } - ] - }, - { - "address": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "idoorToken", - "amount": 100 - } - ] - }, - { - "address": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "naruemonToken", - "amount": 100 - } - ] - }, - { - "address": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zakiToken", - "amount": 1000 - } - ] - }, - { - "address": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "trustToken", - "amount": 1000 - } - ] - }, - { - "address": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "coins": [ - { - "denom": "poldsamToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - } - ], - "stake": { - "pool": { - "loose_unbonded_tokens": 2300, - "unbonded_tokens": 0, - "unbonding_tokens": 0, - "bonded_tokens": 23300, - "unbonded_shares": "0", - "unbonding_shares": "0", - "bonded_shares": "23300", - "inflation_last_time": 0, - "inflation": "9012837/100000000", - "date_last_commission_reset": 0, - "prev_bonded_shares": "0" - }, - "params": { - "inflation_rate_change": "13/100", - "inflation_max": "1/5", - "inflation_min": "7/100", - "goal_bonded": "67/100", - "max_validators": 100, - "bond_denom": "steak" - }, - "bonds": [ - { - "delegator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "validator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "validator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "validator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "validator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "validator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "validator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "validator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "validator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "validator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "validator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "validator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "validator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "validator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "validator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "validator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "validator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "validator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "validator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "validator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "validator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "validator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "validator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "validator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "validator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "validator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "validator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "shares": "1000", - "height": 0 - } - ], - "validators": [ - { - "owner": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "description": { - "moniker": "Dev's Validator", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "109720515B4F8C0858DA3521E448262334534FFD", - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "description": { - "moniker": "", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "description": { - "moniker": "aurel", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "328FBB8EA315D070DF908982A5F91A3618001D20", - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "description": { - "moniker": "cwgoes", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "description": { - "moniker": "BKCM", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "description": { - "moniker": "bdnet", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "description": { - "moniker": "suyu", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "description": { - "moniker": "lino", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "description": { - "moniker": "Staking Facilities", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E04662697134905706A4CCDB822AC6FC11C2E", - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "description": { - "moniker": "default", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E48ED79F1006ED135553768E1D9A768747CF6", - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "description": { - "moniker": "bucky", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "description": { - "moniker": "zach", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A323EC45243D600204BA3D298E3C20322D08C84C", - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "description": { - "moniker": "nuevax", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "description": { - "moniker": "vultr.guest", - "identity": "", - "website": "https://ion.dokia.capital/", - "details": "DokiaValidator" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "description": { - "moniker": "forbole", - "identity": "", - "website": "https://www.forbole.com", - "details": "Recommend. Refer. Reward" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "description": { - "moniker": "nylira", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "description": { - "moniker": "Gold", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "description": { - "moniker": "jla-bsd", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "description": { - "moniker": "figmatt", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "description": { - "moniker": "ATEAM1", - "identity": "", - "website": "", - "details": "ATEAM1" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "description": { - "moniker": "idoor", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "description": { - "moniker": "naruemon", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "description": { - "moniker": "Adrian Brink - Cryptium Labs", - "identity": "", - "website": "https://cryptium.ch", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "description": { - "moniker": "zaki", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "description": { - "moniker": "trust", - "identity": "", - "website": "http://cosmos-trust.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "description": { - "moniker": "proof-of-audit", - "identity": "", - "website": "https://proof-of-audit.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - } - ] - } - } -} diff --git a/cmd/gaia/testnets/gaia-6002/genesis.json b/cmd/gaia/testnets/gaia-6002/genesis.json deleted file mode 100644 index 7f53893a8..000000000 --- a/cmd/gaia/testnets/gaia-6002/genesis.json +++ /dev/null @@ -1,1459 +0,0 @@ -{ - "genesis_time": "2018-06-16T18:29:12.38288148Z", - "chain_id": "gaia-6002", - "consensus_params": { - "block_size_params": { - "max_bytes": 22020096, - "max_txs": 100000, - "max_gas": -1 - }, - "tx_size_params": { - "max_bytes": 10240, - "max_gas": -1 - }, - "block_gossip_params": { - "block_part_size_bytes": 65536 - }, - "evidence_params": { - "max_age": 100000 - } - }, - "validators": [ - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "power": 1000, - "name": "adrian" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "power": 1000, - "name": "zaki" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "power": 100, - "name": "staked" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "power": 1000, - "name": "polsdam" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "power": 1000, - "name": "lino" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "power": 100, - "name": "" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "power": 1000, - "name": "iris" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "power": 1000, - "name": "pbostrom" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "power": 1000, - "name": "aurel" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "power": 1000, - "name": "bucky" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "power": 100, - "name": "cwgoes" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "power": 1000, - "name": "bdnet" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "power": 1000, - "name": "melea-trust" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "power": 1000, - "name": "naruemon" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "power": 1000, - "name": "idoor" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "power": 1000, - "name": "ATEAM1" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "power": 1000, - "name": "figmatt" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "power": 1000, - "name": "jla-bsd" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "power": 1000, - "name": "Gold" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "power": 1000, - "name": "nylira" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "power": 1000, - "name": "BKCM" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "power": 1000, - "name": "Dev's Validator" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "power": 1000, - "name": "Staking Facilities" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "power": 1000, - "name": "nuevax" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "power": 1000, - "name": "vultr.guest" - }, - { - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "power": 1000, - "name": "forebole" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "coins": [ - { - "denom": "devToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "coins": [ - { - "denom": "adrianToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "109720515B4F8C0858DA3521E448262334534FFD", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "coins": [ - { - "denom": "aurelToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "328FBB8EA315D070DF908982A5F91A3618001D20", - "coins": [ - { - "denom": "cwgoesToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "coins": [ - { - "denom": "BKCMToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "coins": [ - { - "denom": "BDToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "coins": [ - { - "denom": "suyuToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "coins": [ - { - "denom": "linoToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "coins": [ - { - "denom": "stakingToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E04662697134905706A4CCDB822AC6FC11C2E", - "coins": [ - { - "denom": "defaultToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "935E48ED79F1006ED135553768E1D9A768747CF6", - "coins": [ - { - "denom": "buckyToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "99FFAEE5BF6040EADA2F26548C4A702619797C9F", - "coins": [ - { - "denom": "kwunyeungToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - }, - { - "address": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zachToken", - "amount": 1000 - } - ] - }, - { - "address": "A323EC45243D600204BA3D298E3C20322D08C84C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "nuevaxToken", - "amount": 1000 - } - ] - }, - { - "address": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "dokiaToken", - "amount": 1000 - } - ] - }, - { - "address": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "forboleToken", - "amount": 1000 - } - ] - }, - { - "address": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "coins": [ - { - "denom": "steak", - "amount": 100 - }, - { - "denom": "pengToken", - "amount": 1000 - } - ] - }, - { - "address": "FD30D5C983FFEDEC069C3DDFCF270E41A556A86E", - "coins": [ - { - "denom": "steak", - "amount": 900 - }, - { - "denom": "faucetToken", - "amount": 10000000 - } - ] - }, - { - "address": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "goldToken", - "amount": 100 - } - ] - }, - { - "address": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "jlaToken", - "amount": 100 - } - ] - }, - { - "address": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "figmattToken", - "amount": 100 - } - ] - }, - { - "address": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "ATEAM1Token", - "amount": 100 - } - ] - }, - { - "address": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "idoorToken", - "amount": 100 - } - ] - }, - { - "address": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "naruemonToken", - "amount": 100 - } - ] - }, - { - "address": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "zakiToken", - "amount": 1000 - } - ] - }, - { - "address": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "coins": [ - { - "denom": "steak", - "amount": 50 - }, - { - "denom": "trustToken", - "amount": 1000 - } - ] - }, - { - "address": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "coins": [ - { - "denom": "poldsamToken", - "amount": 1000 - }, - { - "denom": "steak", - "amount": 50 - } - ] - } - ], - "stake": { - "pool": { - "loose_unbonded_tokens": 2300, - "unbonded_tokens": 0, - "unbonding_tokens": 0, - "bonded_tokens": 23300, - "unbonded_shares": "0", - "unbonding_shares": "0", - "bonded_shares": "23300", - "inflation_last_time": 0, - "inflation": "9012837/100000000", - "date_last_commission_reset": 0, - "prev_bonded_shares": "0" - }, - "params": { - "inflation_rate_change": "13/100", - "inflation_max": "1/5", - "inflation_min": "7/100", - "goal_bonded": "67/100", - "max_validators": 100, - "bond_denom": "steak" - }, - "bonds": [ - { - "delegator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "validator_addr": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "validator_addr": "109720515B4F8C0858DA3521E448262334534FFD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "validator_addr": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "validator_addr": "328FBB8EA315D070DF908982A5F91A3618001D20", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "validator_addr": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "validator_addr": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "validator_addr": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "validator_addr": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "validator_addr": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "validator_addr": "935E04662697134905706A4CCDB822AC6FC11C2E", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "validator_addr": "935E48ED79F1006ED135553768E1D9A768747CF6", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "validator_addr": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "shares": "100", - "height": 0 - }, - { - "delegator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "validator_addr": "A323EC45243D600204BA3D298E3C20322D08C84C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "validator_addr": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "validator_addr": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "validator_addr": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "validator_addr": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "validator_addr": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "validator_addr": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "validator_addr": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "validator_addr": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "validator_addr": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "validator_addr": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "validator_addr": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "validator_addr": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "shares": "1000", - "height": 0 - }, - { - "delegator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "validator_addr": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "shares": "1000", - "height": 0 - } - ], - "validators": [ - { - "owner": "04F01D5AF8DD248130BBE1D0780EA219CE479A9B", - "pub_key": { - "type": "AC26791624DE60", - "value": "PyFJmNrUres3QOkj2BjxplCxrOF+HDFGohi3tRKsToY=" - }, - "description": { - "moniker": "Dev's Validator", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "109720515B4F8C0858DA3521E448262334534FFD", - "pub_key": { - "type": "AC26791624DE60", - "value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A=" - }, - "description": { - "moniker": "", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "10B0899E05A486AE4E5589C39587DF7E9A185872", - "pub_key": { - "type": "AC26791624DE60", - "value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0=" - }, - "description": { - "moniker": "aurel", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "328FBB8EA315D070DF908982A5F91A3618001D20", - "pub_key": { - "type": "AC26791624DE60", - "value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0=" - }, - "description": { - "moniker": "cwgoes", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4062DAFB9ACD4D91051B569CD4B19A26524B314B", - "pub_key": { - "type": "AC26791624DE60", - "value": "QYONAknaJqx3OKPSKraDrOPkx6xssezYtXVS84nZvZE=" - }, - "description": { - "moniker": "BKCM", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "42D76AF31E36EE23CA5366FBB9CE18610CCB9820", - "pub_key": { - "type": "AC26791624DE60", - "value": "TNPLvN6f6QoSLJqGHzIfbraBoSw3emr9Sk2Us94M4gM=" - }, - "description": { - "moniker": "bdnet", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "4B5BE759EB23B0D76C6A60636BD0E3111178794E", - "pub_key": { - "type": "AC26791624DE60", - "value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw=" - }, - "description": { - "moniker": "suyu", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "5A007B81A25AF34B829B79DA508A26E12180BCDB", - "pub_key": { - "type": "AC26791624DE60", - "value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc=" - }, - "description": { - "moniker": "lino", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "83C2788B74E1A410A4E62F1040EAE15F4B6EA3F5", - "pub_key": { - "type": "AC26791624DE60", - "value": "s4ER09+WeX10euzGyK7xDW7+myQVXt3Plup8IHUE4nk=" - }, - "description": { - "moniker": "Staking Facilities", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E04662697134905706A4CCDB822AC6FC11C2E", - "pub_key": { - "type": "AC26791624DE60", - "value": "bIvXwf0qlOy0rO0SY/h8FfsqyW/AMpGL2yUhUNOY7hs=" - }, - "description": { - "moniker": "default", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "935E48ED79F1006ED135553768E1D9A768747CF6", - "pub_key": { - "type": "AC26791624DE60", - "value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o=" - }, - "description": { - "moniker": "bucky", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "9D5723057702E2090405AB5D3B48C45B9ABF4377", - "pub_key": { - "type": "AC26791624DE60", - "value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE=" - }, - "description": { - "moniker": "zach", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "100" - }, - "delegator_shares": "100", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A323EC45243D600204BA3D298E3C20322D08C84C", - "pub_key": { - "type": "AC26791624DE60", - "value": "OPxj9edXgufNEjYNhZKqLgmYnK4A3nGw3rxaFQrHn24=" - }, - "description": { - "moniker": "nuevax", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "A9A3DADDC8BFFAD52BA51C8F4F2E9F62709412DC", - "pub_key": { - "type": "AC26791624DE60", - "value": "Hi2rtbdJdQtOe3Kq4OoD/xkWJbIjIsUI9qgLQ6TlhiM=" - }, - "description": { - "moniker": "vultr.guest", - "identity": "", - "website": "https://ion.dokia.capital/", - "details": "DokiaValidator" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B6834D914FE50F0C743E6A012AB20438CFADFB95", - "pub_key": { - "type": "AC26791624DE60", - "value": "ah3JtmBA7gbxSiimPsLqQlV85gpNOUBJMvnxGx8eVlo=" - }, - "description": { - "moniker": "forbole", - "identity": "", - "website": "https://www.forbole.com", - "details": "Recommend. Refer. Reward" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "B75C2C4309475C91E8DE271BC52CBAC408365B83", - "pub_key": { - "type": "AC26791624DE60", - "value": "VfOsmcON77auerRc9zKwOR+CvL0sj1nA45hS2WqX1xE=" - }, - "description": { - "moniker": "nylira", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C0D0CA58C50B7B02A841E1B27D9A21D939754AC7", - "pub_key": { - "type": "AC26791624DE60", - "value": "KOdWpo4aQFrLxVlkyc66p7m6mBNnPLmGuO4Z4L+CI1Y=" - }, - "description": { - "moniker": "Gold", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C5033FCFB67D7BD7B8546389F125710462D4FB6C", - "pub_key": { - "type": "AC26791624DE60", - "value": "p5ijoVwp2zmA7RkXXvPl+yqdnlaWMwoV2pYIN8bDyFs=" - }, - "description": { - "moniker": "jla-bsd", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "C6CB038C98026D2F17241A3B3166AE7E9488D9AD", - "pub_key": { - "type": "AC26791624DE60", - "value": "vSr94aI+zfF3D8Cr2VtCXPpfgj7t2ck8SlZxRsfn7gk=" - }, - "description": { - "moniker": "figmatt", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D0861E3F22339C507B716102FDD5CA681EDE4F8E", - "pub_key": { - "type": "AC26791624DE60", - "value": "S9urD5q7je21qp5vEobiURdWrtJwvqMsfZGQhb8GOBQ=" - }, - "description": { - "moniker": "ATEAM1", - "identity": "", - "website": "", - "details": "ATEAM1" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D6545CB14FCA7840A295FB0566C27E4B9D526993", - "pub_key": { - "type": "AC26791624DE60", - "value": "rcl+kuM69Un/a7e+fQsQrCEtT1g04tFviOeq2GygSIw=" - }, - "description": { - "moniker": "idoor", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "D841E0DACF3994E6A40126F023F6F32F98A5D89E", - "pub_key": { - "type": "AC26791624DE60", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "description": { - "moniker": "naruemon", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FD8DA5F512A59A30F8698E3CA638D384A68DF977", - "pub_key": { - "type": "AC26791624DE60", - "value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4=" - }, - "description": { - "moniker": "Adrian Brink - Cryptium Labs", - "identity": "", - "website": "https://cryptium.ch", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "ECE57661F0CDCF28EED257B72F86240E57F4A612", - "pub_key": { - "type": "AC26791624DE60", - "value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY=" - }, - "description": { - "moniker": "zaki", - "identity": "", - "website": "", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "EFE597F7A90D3F3E7599B25259449628E2C4AFAD", - "pub_key": { - "type": "AC26791624DE60", - "value": "cvGYknYP9XMUzqlXZde7lRpvAp/kZiSRYHg66krJNxQ=" - }, - "description": { - "moniker": "trust", - "identity": "", - "website": "http://cosmos-trust.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - }, - { - "owner": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5", - "pub_key": { - "type": "AC26791624DE60", - "value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8=" - }, - "description": { - "moniker": "proof-of-audit", - "identity": "", - "website": "https://proof-of-audit.com", - "details": "" - }, - "revoked": false, - "pool_shares": { - "status": 2, - "amount": "1000" - }, - "delegator_shares": "1000", - "bond_height": 0, - "bond_intra_tx_counter": 0, - "commision": "0/1", - "commission_max": "0/1", - "commission_change_rate": "0/1", - "commission_change_rate_today": "0/1", - "prev_bonded_shares": "0/1" - } - ] - } - } -} diff --git a/cmd/gaia/testnets/gaia-7000/genesis.json b/cmd/gaia/testnets/gaia-7000/genesis.json deleted file mode 100644 index 7ada516d4..000000000 --- a/cmd/gaia/testnets/gaia-7000/genesis.json +++ /dev/null @@ -1,5680 +0,0 @@ -{ - "genesis_time": "2018-07-16T19:57:28.971479541Z", - "chain_id": "gaia-7000", - "consensus_params": { - "block_size_params": { - "max_bytes": "22020096", - "max_txs": "10000", - "max_gas": "-1" - }, - "tx_size_params": { - "max_bytes": "10240", - "max_gas": "-1" - }, - "block_gossip_params": { - "block_part_size_bytes": "65536" - }, - "evidence_params": { - "max_age": "100000" - } - }, - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MRCeBDANSjH6IsxO0z6tRe+xqoZvIGhdfl1t+SXGUpM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "tOEqjO2t51PEgO9Tv0B7qM0yPmy1n5tMa3Beg0tp3ns=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "S8s6fdAQNQ3bN9SNVAsHB/j8uv1CM1roxeLesL+fh4g=" - }, - "power": "100", - "name": "validatorluigi001" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "k3YLQYEN2QMP6XITRsBmgb+pNGhJ5Jbg0bzUW977kK0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "EREUrXXl1OJqLQag0P4h6vJ2H+8GEwyNAjgn1XEJU+I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "heNintBalqaJwCOjLb9+mX/cQ1ytMlV7ZroPIlkwZqo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nb2oRB12DlEQkFn7KSjSVkj5rDoSTsuBFa09+gmNJ7o=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bZSEBDNIOr0xJ/PxaAScJIyG6hqFtryBAMNwghAOTTU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8K3clCjVU33BTIpUhdahGmu++WxHj4NUE9krCRkk++s=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RBuRRNEzA9RA1Wrdi9PPFQJ29/n/bqN9O2tQv9Gq248=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RwPRoiY5C0covekqbr3VrQwxWGHioUUIf2+TOq8LIC0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2qtEBT+Tc+SD2wJsdrVMHXrBKfvesxtmtSKDK5fXwA0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gU5mmVLUSzn/fIEMgiiB4LARRoWlqjUGHr3A4SndWO8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "xlO2cnii42KisAn8OcstC/3XV5+I0FlcSbWuyy5MVA8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "q5ezDn4DcWFPWvMayPJI35nXr//jjF8fGHsuiHjpDcU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PSqbJOwglJb1yrj3aWebBpXb2ujXcR037s1Cyj2HoW4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A6GzeXUM3vsXaDAEYMSDgSKkqn9AoUYjs8empH46MGY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "81fx09BivOOxeGL7QisF8aKRZjjcARpiSaCOX9mJfY8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UjTvuOew2EaooduJBiYmBWeF5ai0yFJG8uio5YXpJgg=" - }, - "power": "1", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "y7p9JSVZBnRxjAI9v5Pxl37hMtyuHf6B4Ghqzm6+ii0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oG8Q5o+SN4wqMLvlIfVgQPnsQzNEKeH0D/XGM8JlGrY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PxJbo5FKA6mXtgwclRQVNIjOCQK3Q7WkLQrvM9lYbGI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Q/UShqqVDOUSNYBrR1G/1X1s+YXEVXEJzeXmYvfYIr0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "uEWWDBwFW+/BpTCvNCLW7AP98hndBukzSbrwCb7sooo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MZi48DJZOgRbE0ZStR66omv6Ez1Wkjvf2D/41q6Nd0I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Go9GXHI6SCQo2QKMxkAkgYLhfo3XrVjWLR2nE2AvYyk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "P9RgE4RMQT/aHap2oICpwpgKeBAwxPUwuU9zIffKFNM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "1+EkFYvTDmz4WQRbK+kznRHoaZVLludtkDrMuM6h++E=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "QEMDwUVoyJT7MNfOYKa25xU+Lnsz/ciH8rFUri4diLI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "lUMCRAeu47BsOhNvCQTQJQeB68z0/VaElC9j5gDt9y8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VnAr7ZIjvUXpWmzbkt8skHp0oRNc3V89SfvgaZydwfw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "u4GEbsk9IEF56V1am5dRtAWXz4iFQkO03FVL87BZXIM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BaaCxmYHKJ6obIzTCdRtjw1cc8d2mUJcMbLWCjf1aLo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "N3K5kDdfcKJurfaa6s2zfKgtYvz1Pagz7VWi9ZfX8yM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "DsTbM0AgHfhSUKvOGkxudDOY3ojYT6bifhpelqHs8+s=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j9be+ddLChInrFz6/820/uYh4WZBzlp61klyJBDy/ZY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xi7nIgj4PqVXrpKLfJhcyxyVY1d3HRo72sKKPDmuU78=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2p8s/pRBZPjYWKKMlR7AOXypDzDmPo762iXlKpCwtco=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nsofE1FmSr1TiDR0gfnxfMDQ8o2pC+1NE7Oa9ceztSg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WvmTBjsCN4ueGpEdySRwsRC5knBRLfY439/e4mG+YAY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "c0i2uKsYBv8fubnI60lZIWA1y4zw1bFgsq5MmWBHKak=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "AJR2ex094A1nJEWQsZYjALWsrSl1/huGZ37z2ZsMrpg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "LSDd6ab46sHxwJSrg5YLpsPG2o6EcsZ3rDikpHzMNmI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dnFjFoTM9sP/RjQkXBK1YpYn3v5W+j0+g/OfUHS4xu8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "L0I4JoDfktbDWe0fCDL/nQlBPkF5mNgqamnM5JKJ1Uc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dPpZD53AbAMtW6sK+rTnXYe2GGGoSCNWsCtsmArLiIs=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VakMQSPBEuSC9Nwuv8WWhrZVUmH31bUR4+G6pJhkgE8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KI+kCESWD9cB8se4uxRrFVAI5viyNNUXUyMCc903yQc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8Qu1LFMt7qlZNmYQWrsXUA80aIx0rrFPPXs2s6NBdU8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WRsXnLz3gf8o4lYYeCZjAXgPU1cdmOOYPdy7aY63iIA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "R/3f7VruxWpu+2hiHlVpplTwoOou5kfQI1k/6/9H/y8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "HjSC7VkhKih6xMhudlqfaFE8ZZnP8RKJPv4iqR7RhcE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cLM/HeUFsXlnYnYod695u6NBDS0trMq8sVRdABnF7uc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Epd2FDKZwDybzT38Z7WB0y2jiLn9/2OLzmY3Zu18l6I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ENAVynNXVpj/IdYx9kCPKaPs4bWSxRIHNlmS9QiDuZQ=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j2w5BFOnZTrPN4SFpmQyfRomnUwbEbz1A+kr3z1icjo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "I2ILaY31gonxYQhlIk4PFUIN+Pk7+9dDTK1C/s+Vcb0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "3wRufybSUsTMnUeQkP74uJNDRKeM8jBLAS64T0BRfpY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2gOiMAdnIdND4cA75E7naQdyyIYDAdcjF3uO6OiEZlU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2S8Y/vnLM3W+MYxNCxcUItIBfdZL/T4A8vRg89n0wLg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UBTju7UZfXLVPPYb1a8gPZ69BeCv2Fho7YVo2EUbxKc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "0HqB2x6x5HzeozpHatePECw07x1UcDdSz8kQGNznnA8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "H0SIA/BU6Xj8oT5bQkvLpEITN3CqFLbMeBcQ72NZrAE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xnh8TL3BbIs9VTUenmnx6r2UAHpGCj3G9FV0mzc+mU4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "X62YB48gO2SsWGnjYxH+aGfLQcjnP+T0hnErdWZ859g=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8pfpbIxBBiu88hpxS3CeRpv7kClEjl8SwVgckDNBGlE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UuxXNPImsE5Wp+utGfJywZBHuuGE4RmL0CArc6td82w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Sl3NKLaYEgDaovqTkKVZh2ihRFbSmyVjC63wpv3ecdc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SYjCs2AlY04xdfJGPD+gyO9NZ/zQ0Lfb/TLrjgOLS68=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oI1+4FoeI/knjsjDyCJtgZPaeyKON8tCTcM9QX0BHa8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nts1nu73aBgIdSaYye4coIuE1iBNeCuTZZC8LQ37ac8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NQX4yKpOztKrmgBhGIC5WOALOLOq3LTpbzsN4ZLXGec=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BB4a/Xh5z+dkGCRlF+pSGC3iDOoDrFse/xzQAtmxMF4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ydjx2ea+PVuChrny6X2dluJwyXta+BsNQRsgHXp8fXw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "pPGLc4NhNaehdoV2antWuyr0GmBVEG1NhD9NiSRrTi0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VBVHOLnWGptY26J0wqXoZI2Dnu96pccMb08zlsaxPCQ=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "aUViYC2znC55sleHfmsIN9hZ45SbYPbDcYA0gVzglsc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "riYrMXBFLavmf4MU/Ly7emDlciVqfB2/zxJoRsBUlfY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "F2wCn9rKafNZsYZwoLGkSQIpr3rk86cjYyuhSjsjRaE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ugb3W6W7WL9Vc4KiSBWIaowBfpqJlzbfBSfrIqZW06A=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gJDxhwAE6GeGCKQeVaNZ5is7+7MFHXtOG0UsnguKdoA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b9RSkt+WmMxVHQExQH0IMPpnR9zDAaJwz/mv1gtyRVY=" - }, - "power": "100", - "name": "smartpesa" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "569Sb+Wpo8VFqXRi4cQhlOD9kS8uBgmJ2rntY3GLtzY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SNwrT1B+A4g6TY7x0QzVrmVbcbl3cHXzXdD1tFHxLNo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "K4kLogLtZxqrYSqRVJfrFm9tUG+Tc3QWXWIewnAgI9w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "TwzOJ4GcN+ZTswub4R8488SrKeWXjY/PaqCF5neXJig=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JXW8iTiWG28E05ZFJIKvCOBwI2RrH/BOBL/MluTZ6+I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A3zUdVcpj4H+HRZmRW5xixj4dzMgqD7be9GrdXcjdns=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "7RhnD9OAZEJ4SV6V3LOZ1gGWubtX25457wCQq+AYYPI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "66j9af4xDJSblMLS+mFbp7d8TaFGu0FOo+0MwEYm2lE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8DScmobjJQmkN44K2xiZkESM/O9MJK/DqlggnIPLpso=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "4JoJuRfaANhdM1x3AWRo1/Cj9DH3VA+fi1SynzknV+w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cCoFsZzKZ9SQZbHe4NueVObIezP6ts0tRTZ/aN96dig=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Zp4tk/ieqplJF8xMeef9HV8bYpHSY+3hJ2sH7PfCX1I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "jj0Y/Fy8JSJR3g+PHU6Ce0ecYwHGUVJ4bVyR7WwcyLI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "XQDVMXja3kFk5Jb47BsqJmzcDsM4lE9+r+f/J3O5Jms=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oL/QCr7LEOivyTqpGrmwVd1r+hYI2WB5+kSVzpDMxx4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "eeImG09hOPo1W7j7lKepN/Lx6I9GGHqVBVEKmznxACc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Abws3eXrUFAH8LeZJIcECakPL945TTmFsBlXONOUeII=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PEg/D54SoiKZ+pic0Z0RzZa/vfYNAAf4kzSc5UKXDYk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "omAzuJps8KX3/iOC1LjwkMPMH3c6tjfLXwCNWXRBdWw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nctikQSpoLRl5kV6KarIS761QvEOZCWw6nvc48xWhic=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NrTRAbZnBqJpW9lRW6LxXxE7EV++y7WiIRV0ifRLovA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "W0rP8sv4Ae/LZOqlBA9evvYARDt79WpFaI26jw/9Tfk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JdfJDlE46456GWp+AkSZhzlkUQI41f8aX7611oiWUSc=" - }, - "power": "100", - "name": "" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "cosmosaccaddr1c2dkaym4teqw6jl9jkq8eu8nf4wzn2lgf4ydyt", - "coins": [ - { - "denom": "faucetToken", - "amount": "1000000" - }, - { - "denom": "steak", - "amount": "10000000" - } - ] - }, - { - "address": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "coins": [ - { - "denom": "jlandrewsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "coins": [ - { - "denom": "jackToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "coins": [ - { - "denom": "luigi001Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "coins": [ - { - "denom": "irisToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "coins": [ - { - "denom": "irisToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "coins": [ - { - "denom": "TropicalMongoXToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "coins": [ - { - "denom": "wingmanToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "coins": [ - { - "denom": "Nemea7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "coins": [ - { - "denom": "infinite-castingToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "coins": [ - { - "denom": "cwgoesToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "coins": [ - { - "denom": "lunamintToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "coins": [ - { - "denom": "skoed-validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "coins": [ - { - "denom": "starfishToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "coins": [ - { - "denom": "jjangg96Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "coins": [ - { - "denom": "iaspirationiToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "coins": [ - { - "denom": "21e800Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "coins": [ - { - "denom": "spptest1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "coins": [ - { - "denom": "windmillToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "coins": [ - { - "denom": "pbostrom/Mythos-1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "coins": [ - { - "denom": "BarytToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "coins": [ - { - "denom": "P2P.ORG ValidatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "coins": [ - { - "denom": "oleary-labsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "coins": [ - { - "denom": "wancloudsentryToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "coins": [ - { - "denom": "space4Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "coins": [ - { - "denom": "colony-finderToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "coins": [ - { - "denom": "sparkpool-validator-02Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "coins": [ - { - "denom": "mining-shipToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "coins": [ - { - "denom": "StakedToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "coins": [ - { - "denom": "nyliraToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "coins": [ - { - "denom": "liangpingToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "coins": [ - { - "denom": "SVNode01Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "coins": [ - { - "denom": "vhxnode1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "coins": [ - { - "denom": "gregToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "coins": [ - { - "denom": "bucksterToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "coins": [ - { - "denom": "grass-fedToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "coins": [ - { - "denom": "ATEAM1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "coins": [ - { - "denom": "BFF-Validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "coins": [ - { - "denom": "redbricks7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "coins": [ - { - "denom": "kittyfishToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "coins": [ - { - "denom": "ForboleToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "coins": [ - { - "denom": "coinoneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "coins": [ - { - "denom": "bmen-companyToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "coins": [ - { - "denom": "2400bpsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "coins": [ - { - "denom": "devToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "coins": [ - { - "denom": "w1m3lToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "coins": [ - { - "denom": "aetherToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "coins": [ - { - "denom": "JColToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "coins": [ - { - "denom": "SaiKrishnaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "coins": [ - { - "denom": "UmbrellaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "coins": [ - { - "denom": "@MarceldeveloperToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "coins": [ - { - "denom": "stereo-watcherToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "coins": [ - { - "denom": "cosmosToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "coins": [ - { - "denom": "stake.zoneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "coins": [ - { - "denom": "firstblock.ioToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "coins": [ - { - "denom": "shensiToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "coins": [ - { - "denom": "figmentToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "coins": [ - { - "denom": "iqlusionToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "coins": [ - { - "denom": "cosmosthecatToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "coins": [ - { - "denom": "snaticoToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "coins": [ - { - "denom": "mpaxeNodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "coins": [ - { - "denom": "joltz-secureware.ioToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "coins": [ - { - "denom": "mwnode1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "coins": [ - { - "denom": "VNode01Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "coins": [ - { - "denom": "7768Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "coins": [ - { - "denom": "block3.communityToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "coins": [ - { - "denom": "4455Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "coins": [ - { - "denom": "dooroomeeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "coins": [ - { - "denom": "sheiudToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "coins": [ - { - "denom": "Staking Facilities ValidatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "coins": [ - { - "denom": "ritter-rammToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "coins": [ - { - "denom": "meteor-discoverToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "coins": [ - { - "denom": "COSMODROMEToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "coins": [ - { - "denom": "broadleaf7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "coins": [ - { - "denom": "ravenclubToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "coins": [ - { - "denom": "dokia-capitalToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "coins": [ - { - "denom": "chainflow08Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "coins": [ - { - "denom": "MiaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "coins": [ - { - "denom": "sikka.techToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "coins": [ - { - "denom": "certus.oneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "coins": [ - { - "denom": "Gold2Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "coins": [ - { - "denom": "idoor7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "coins": [ - { - "denom": "ironforkToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "coins": [ - { - "denom": "sunny-mintorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "coins": [ - { - "denom": "BlissDynamicsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "coins": [ - { - "denom": "smartpesaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "coins": [ - { - "denom": "ianstreamToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "coins": [ - { - "denom": "TruNodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "coins": [ - { - "denom": "abcinToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "coins": [ - { - "denom": "kochacolajToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "coins": [ - { - "denom": "D2R-validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "coins": [ - { - "denom": "juelianshanaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "coins": [ - { - "denom": "lambda-mixerToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "coins": [ - { - "denom": "bkcmToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "coins": [ - { - "denom": "ramihanToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "coins": [ - { - "denom": "davinchcodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "coins": [ - { - "denom": "DoriToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "coins": [ - { - "denom": "daefreecaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "coins": [ - { - "denom": "nuevaxToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "coins": [ - { - "denom": "inschain_validatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "coins": [ - { - "denom": "gruberxToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "coins": [ - { - "denom": "meleatrustToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "coins": [ - { - "denom": "Cosmodator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "coins": [ - { - "denom": "bharvestToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "coins": [ - { - "denom": "cryptiumToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "coins": [ - { - "denom": "finalityToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "coins": [ - { - "denom": "coscloudToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "coins": [ - { - "denom": "xiaochinaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "coins": [ - { - "denom": "gazua1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - } - ], - "stake": { - "pool": { - "loose_tokens": "16200", - "bonded_tokens": "0", - "inflation_last_time": "0", - "inflation": "7/100", - "date_last_commission_reset": "0", - "prev_bonded_shares": "0" - }, - "params": { - "inflation_rate_change": "13/100", - "inflation_max": "1/5", - "inflation_min": "7/100", - "goal_bonded": "67/100", - "unbonding_time": "86400", - "max_validators": 100, - "bond_denom": "steak" - }, - "validators": [ - { - "owner": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MRCeBDANSjH6IsxO0z6tRe+xqoZvIGhdfl1t+SXGUpM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jlandrews", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "tOEqjO2t51PEgO9Tv0B7qM0yPmy1n5tMa3Beg0tp3ns=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jack", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "S8s6fdAQNQ3bN9SNVAsHB/j8uv1CM1roxeLesL+fh4g=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "luigi001", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iris", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iris", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "k3YLQYEN2QMP6XITRsBmgb+pNGhJ5Jbg0bzUW977kK0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "TropicalMongoX", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "EREUrXXl1OJqLQag0P4h6vJ2H+8GEwyNAjgn1XEJU+I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "wingman", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "heNintBalqaJwCOjLb9+mX/cQ1ytMlV7ZroPIlkwZqo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Nemea7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nb2oRB12DlEQkFn7KSjSVkj5rDoSTsuBFa09+gmNJ7o=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "infinite-casting", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bZSEBDNIOr0xJ/PxaAScJIyG6hqFtryBAMNwghAOTTU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cwgoes", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8K3clCjVU33BTIpUhdahGmu++WxHj4NUE9krCRkk++s=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "lunamint", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RBuRRNEzA9RA1Wrdi9PPFQJ29/n/bqN9O2tQv9Gq248=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "skoed-validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RwPRoiY5C0covekqbr3VrQwxWGHioUUIf2+TOq8LIC0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "starfish", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2qtEBT+Tc+SD2wJsdrVMHXrBKfvesxtmtSKDK5fXwA0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jjangg96", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gU5mmVLUSzn/fIEMgiiB4LARRoWlqjUGHr3A4SndWO8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iaspirationi", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "xlO2cnii42KisAn8OcstC/3XV5+I0FlcSbWuyy5MVA8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "21e800", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "q5ezDn4DcWFPWvMayPJI35nXr//jjF8fGHsuiHjpDcU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "spptest1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PSqbJOwglJb1yrj3aWebBpXb2ujXcR037s1Cyj2HoW4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "windmill", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A6GzeXUM3vsXaDAEYMSDgSKkqn9AoUYjs8empH46MGY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "pbostrom/Mythos-1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "81fx09BivOOxeGL7QisF8aKRZjjcARpiSaCOX9mJfY8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Baryt", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UjTvuOew2EaooduJBiYmBWeF5ai0yFJG8uio5YXpJgg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "P2P.ORG Validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "y7p9JSVZBnRxjAI9v5Pxl37hMtyuHf6B4Ghqzm6+ii0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "oleary-labs", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oG8Q5o+SN4wqMLvlIfVgQPnsQzNEKeH0D/XGM8JlGrY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "wancloudsentry", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PxJbo5FKA6mXtgwclRQVNIjOCQK3Q7WkLQrvM9lYbGI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "space4", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Q/UShqqVDOUSNYBrR1G/1X1s+YXEVXEJzeXmYvfYIr0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "colony-finder", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "uEWWDBwFW+/BpTCvNCLW7AP98hndBukzSbrwCb7sooo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sparkpool-validator-02", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MZi48DJZOgRbE0ZStR66omv6Ez1Wkjvf2D/41q6Nd0I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mining-ship", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Go9GXHI6SCQo2QKMxkAkgYLhfo3XrVjWLR2nE2AvYyk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Staked", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "P9RgE4RMQT/aHap2oICpwpgKeBAwxPUwuU9zIffKFNM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "nylira", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "1+EkFYvTDmz4WQRbK+kznRHoaZVLludtkDrMuM6h++E=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "liangping", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "QEMDwUVoyJT7MNfOYKa25xU+Lnsz/ciH8rFUri4diLI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "SVNode01", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "lUMCRAeu47BsOhNvCQTQJQeB68z0/VaElC9j5gDt9y8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "vhxnode1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VnAr7ZIjvUXpWmzbkt8skHp0oRNc3V89SfvgaZydwfw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "greg", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "u4GEbsk9IEF56V1am5dRtAWXz4iFQkO03FVL87BZXIM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "buckster", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BaaCxmYHKJ6obIzTCdRtjw1cc8d2mUJcMbLWCjf1aLo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "grass-fed", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "N3K5kDdfcKJurfaa6s2zfKgtYvz1Pagz7VWi9ZfX8yM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ATEAM1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "DsTbM0AgHfhSUKvOGkxudDOY3ojYT6bifhpelqHs8+s=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "BFF-Validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j9be+ddLChInrFz6/820/uYh4WZBzlp61klyJBDy/ZY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "redbricks7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xi7nIgj4PqVXrpKLfJhcyxyVY1d3HRo72sKKPDmuU78=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "kittyfish", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2p8s/pRBZPjYWKKMlR7AOXypDzDmPo762iXlKpCwtco=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Forbole", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nsofE1FmSr1TiDR0gfnxfMDQ8o2pC+1NE7Oa9ceztSg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "coinone", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WvmTBjsCN4ueGpEdySRwsRC5knBRLfY439/e4mG+YAY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bmen-company", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "c0i2uKsYBv8fubnI60lZIWA1y4zw1bFgsq5MmWBHKak=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "2400bps", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "AJR2ex094A1nJEWQsZYjALWsrSl1/huGZ37z2ZsMrpg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dev", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "LSDd6ab46sHxwJSrg5YLpsPG2o6EcsZ3rDikpHzMNmI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "w1m3l", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dnFjFoTM9sP/RjQkXBK1YpYn3v5W+j0+g/OfUHS4xu8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "aether", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "L0I4JoDfktbDWe0fCDL/nQlBPkF5mNgqamnM5JKJ1Uc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "JCol", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dPpZD53AbAMtW6sK+rTnXYe2GGGoSCNWsCtsmArLiIs=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "SaiKrishna", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VakMQSPBEuSC9Nwuv8WWhrZVUmH31bUR4+G6pJhkgE8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Umbrella", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KI+kCESWD9cB8se4uxRrFVAI5viyNNUXUyMCc903yQc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "@Marceldeveloper", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8Qu1LFMt7qlZNmYQWrsXUA80aIx0rrFPPXs2s6NBdU8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "stereo-watcher", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WRsXnLz3gf8o4lYYeCZjAXgPU1cdmOOYPdy7aY63iIA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cosmos", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "R/3f7VruxWpu+2hiHlVpplTwoOou5kfQI1k/6/9H/y8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "stake.zone", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "HjSC7VkhKih6xMhudlqfaFE8ZZnP8RKJPv4iqR7RhcE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "firstblock.io", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cLM/HeUFsXlnYnYod695u6NBDS0trMq8sVRdABnF7uc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "shensi", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Epd2FDKZwDybzT38Z7WB0y2jiLn9/2OLzmY3Zu18l6I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "figment", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ENAVynNXVpj/IdYx9kCPKaPs4bWSxRIHNlmS9QiDuZQ=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iqlusion", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j2w5BFOnZTrPN4SFpmQyfRomnUwbEbz1A+kr3z1icjo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cosmosthecat", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "I2ILaY31gonxYQhlIk4PFUIN+Pk7+9dDTK1C/s+Vcb0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "snatico", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "3wRufybSUsTMnUeQkP74uJNDRKeM8jBLAS64T0BRfpY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mpaxeNode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2gOiMAdnIdND4cA75E7naQdyyIYDAdcjF3uO6OiEZlU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "joltz-secureware.io", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2S8Y/vnLM3W+MYxNCxcUItIBfdZL/T4A8vRg89n0wLg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mwnode1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "VNode01", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UBTju7UZfXLVPPYb1a8gPZ69BeCv2Fho7YVo2EUbxKc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "7768", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "0HqB2x6x5HzeozpHatePECw07x1UcDdSz8kQGNznnA8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "block3.community", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "H0SIA/BU6Xj8oT5bQkvLpEITN3CqFLbMeBcQ72NZrAE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "4455", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xnh8TL3BbIs9VTUenmnx6r2UAHpGCj3G9FV0mzc+mU4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dooroomee", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "X62YB48gO2SsWGnjYxH+aGfLQcjnP+T0hnErdWZ859g=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sheiud", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8pfpbIxBBiu88hpxS3CeRpv7kClEjl8SwVgckDNBGlE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Staking Facilities Validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UuxXNPImsE5Wp+utGfJywZBHuuGE4RmL0CArc6td82w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ritter-ramm", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Sl3NKLaYEgDaovqTkKVZh2ihRFbSmyVjC63wpv3ecdc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "meteor-discover", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SYjCs2AlY04xdfJGPD+gyO9NZ/zQ0Lfb/TLrjgOLS68=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "COSMODROME", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oI1+4FoeI/knjsjDyCJtgZPaeyKON8tCTcM9QX0BHa8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "broadleaf7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nts1nu73aBgIdSaYye4coIuE1iBNeCuTZZC8LQ37ac8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ravenclub", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NQX4yKpOztKrmgBhGIC5WOALOLOq3LTpbzsN4ZLXGec=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dokia-capital", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BB4a/Xh5z+dkGCRlF+pSGC3iDOoDrFse/xzQAtmxMF4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "chainflow08", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ydjx2ea+PVuChrny6X2dluJwyXta+BsNQRsgHXp8fXw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Mia", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "pPGLc4NhNaehdoV2antWuyr0GmBVEG1NhD9NiSRrTi0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sikka.tech", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VBVHOLnWGptY26J0wqXoZI2Dnu96pccMb08zlsaxPCQ=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "certus.one", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "aUViYC2znC55sleHfmsIN9hZ45SbYPbDcYA0gVzglsc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Gold2", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "riYrMXBFLavmf4MU/Ly7emDlciVqfB2/zxJoRsBUlfY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "idoor7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "F2wCn9rKafNZsYZwoLGkSQIpr3rk86cjYyuhSjsjRaE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ironfork", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ugb3W6W7WL9Vc4KiSBWIaowBfpqJlzbfBSfrIqZW06A=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sunny-mintor", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gJDxhwAE6GeGCKQeVaNZ5is7+7MFHXtOG0UsnguKdoA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "BlissDynamics", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b9RSkt+WmMxVHQExQH0IMPpnR9zDAaJwz/mv1gtyRVY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "smartpesa", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "569Sb+Wpo8VFqXRi4cQhlOD9kS8uBgmJ2rntY3GLtzY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ianstream", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SNwrT1B+A4g6TY7x0QzVrmVbcbl3cHXzXdD1tFHxLNo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "TruNode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "K4kLogLtZxqrYSqRVJfrFm9tUG+Tc3QWXWIewnAgI9w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "abcin", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "TwzOJ4GcN+ZTswub4R8488SrKeWXjY/PaqCF5neXJig=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "kochacolaj", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JXW8iTiWG28E05ZFJIKvCOBwI2RrH/BOBL/MluTZ6+I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "D2R-validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A3zUdVcpj4H+HRZmRW5xixj4dzMgqD7be9GrdXcjdns=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "juelianshana", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "7RhnD9OAZEJ4SV6V3LOZ1gGWubtX25457wCQq+AYYPI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "lambda-mixer", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "66j9af4xDJSblMLS+mFbp7d8TaFGu0FOo+0MwEYm2lE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bkcm", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8DScmobjJQmkN44K2xiZkESM/O9MJK/DqlggnIPLpso=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ramihan", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "4JoJuRfaANhdM1x3AWRo1/Cj9DH3VA+fi1SynzknV+w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "davinchcode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cCoFsZzKZ9SQZbHe4NueVObIezP6ts0tRTZ/aN96dig=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Dori", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Zp4tk/ieqplJF8xMeef9HV8bYpHSY+3hJ2sH7PfCX1I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "daefreeca", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "jj0Y/Fy8JSJR3g+PHU6Ce0ecYwHGUVJ4bVyR7WwcyLI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "nuevax", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "XQDVMXja3kFk5Jb47BsqJmzcDsM4lE9+r+f/J3O5Jms=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "inschain_validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oL/QCr7LEOivyTqpGrmwVd1r+hYI2WB5+kSVzpDMxx4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "gruberx", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "eeImG09hOPo1W7j7lKepN/Lx6I9GGHqVBVEKmznxACc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "meleatrust", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Abws3eXrUFAH8LeZJIcECakPL945TTmFsBlXONOUeII=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Cosmodator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PEg/D54SoiKZ+pic0Z0RzZa/vfYNAAf4kzSc5UKXDYk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bharvest", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "omAzuJps8KX3/iOC1LjwkMPMH3c6tjfLXwCNWXRBdWw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Adrian Brink - Cryptium Labs", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nctikQSpoLRl5kV6KarIS761QvEOZCWw6nvc48xWhic=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "finality", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NrTRAbZnBqJpW9lRW6LxXxE7EV++y7WiIRV0ifRLovA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "coscloud", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "W0rP8sv4Ae/LZOqlBA9evvYARDt79WpFaI26jw/9Tfk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "xiaochina", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JdfJDlE46456GWp+AkSZhzlkUQI41f8aX7611oiWUSc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "gazua1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - } - ], - "bonds": [ - { - "delegator_addr": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "validator_addr": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "validator_addr": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "validator_addr": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "validator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "validator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "validator_addr": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "validator_addr": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "validator_addr": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "validator_addr": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "validator_addr": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "validator_addr": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "validator_addr": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "validator_addr": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "validator_addr": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "validator_addr": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "validator_addr": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "validator_addr": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "validator_addr": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "validator_addr": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "validator_addr": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "validator_addr": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "validator_addr": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "validator_addr": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "validator_addr": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "validator_addr": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "validator_addr": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "validator_addr": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "validator_addr": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "validator_addr": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "validator_addr": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "validator_addr": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "validator_addr": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "validator_addr": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "validator_addr": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "validator_addr": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "validator_addr": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "validator_addr": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "validator_addr": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "validator_addr": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "validator_addr": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "validator_addr": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "validator_addr": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "validator_addr": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "validator_addr": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "validator_addr": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "validator_addr": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "validator_addr": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "validator_addr": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "validator_addr": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "validator_addr": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "validator_addr": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "validator_addr": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "validator_addr": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "validator_addr": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "validator_addr": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "validator_addr": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "validator_addr": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "validator_addr": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "validator_addr": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "validator_addr": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "validator_addr": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "validator_addr": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "validator_addr": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "validator_addr": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "validator_addr": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "validator_addr": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "validator_addr": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "validator_addr": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "validator_addr": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "validator_addr": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "validator_addr": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "validator_addr": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "validator_addr": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "validator_addr": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "validator_addr": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "validator_addr": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "validator_addr": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "validator_addr": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "validator_addr": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "validator_addr": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "validator_addr": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "validator_addr": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "validator_addr": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "validator_addr": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "validator_addr": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "validator_addr": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "validator_addr": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "validator_addr": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "validator_addr": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "validator_addr": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "validator_addr": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "validator_addr": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "validator_addr": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "validator_addr": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "validator_addr": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "validator_addr": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "validator_addr": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "validator_addr": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "validator_addr": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "validator_addr": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "validator_addr": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "validator_addr": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "validator_addr": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "validator_addr": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "validator_addr": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "validator_addr": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "validator_addr": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "validator_addr": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "shares": "100", - "height": "0" - } - ] - } - } -} \ No newline at end of file diff --git a/cmd/gaia/testnets/gaia-7001/genesis.json b/cmd/gaia/testnets/gaia-7001/genesis.json deleted file mode 100644 index 48db5a4ed..000000000 --- a/cmd/gaia/testnets/gaia-7001/genesis.json +++ /dev/null @@ -1,5628 +0,0 @@ -{ - "genesis_time": "2018-07-17T07:19:26.795692941Z", - "chain_id": "gaia-7001", - "consensus_params": { - "block_size_params": { - "max_bytes": "22020096", - "max_txs": "10000", - "max_gas": "-1" - }, - "tx_size_params": { - "max_bytes": "10240", - "max_gas": "-1" - }, - "block_gossip_params": { - "block_part_size_bytes": "65536" - }, - "evidence_params": { - "max_age": "100000" - } - }, - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MRCeBDANSjH6IsxO0z6tRe+xqoZvIGhdfl1t+SXGUpM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "tOEqjO2t51PEgO9Tv0B7qM0yPmy1n5tMa3Beg0tp3ns=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "S8s6fdAQNQ3bN9SNVAsHB/j8uv1CM1roxeLesL+fh4g=" - }, - "power": "100", - "name": "validatorluigi001" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "k3YLQYEN2QMP6XITRsBmgb+pNGhJ5Jbg0bzUW977kK0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "EREUrXXl1OJqLQag0P4h6vJ2H+8GEwyNAjgn1XEJU+I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "heNintBalqaJwCOjLb9+mX/cQ1ytMlV7ZroPIlkwZqo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nb2oRB12DlEQkFn7KSjSVkj5rDoSTsuBFa09+gmNJ7o=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bZSEBDNIOr0xJ/PxaAScJIyG6hqFtryBAMNwghAOTTU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8K3clCjVU33BTIpUhdahGmu++WxHj4NUE9krCRkk++s=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RBuRRNEzA9RA1Wrdi9PPFQJ29/n/bqN9O2tQv9Gq248=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RwPRoiY5C0covekqbr3VrQwxWGHioUUIf2+TOq8LIC0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2qtEBT+Tc+SD2wJsdrVMHXrBKfvesxtmtSKDK5fXwA0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gU5mmVLUSzn/fIEMgiiB4LARRoWlqjUGHr3A4SndWO8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "xlO2cnii42KisAn8OcstC/3XV5+I0FlcSbWuyy5MVA8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "q5ezDn4DcWFPWvMayPJI35nXr//jjF8fGHsuiHjpDcU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PSqbJOwglJb1yrj3aWebBpXb2ujXcR037s1Cyj2HoW4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A6GzeXUM3vsXaDAEYMSDgSKkqn9AoUYjs8empH46MGY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "81fx09BivOOxeGL7QisF8aKRZjjcARpiSaCOX9mJfY8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UjTvuOew2EaooduJBiYmBWeF5ai0yFJG8uio5YXpJgg=" - }, - "power": "1", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "y7p9JSVZBnRxjAI9v5Pxl37hMtyuHf6B4Ghqzm6+ii0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oG8Q5o+SN4wqMLvlIfVgQPnsQzNEKeH0D/XGM8JlGrY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PxJbo5FKA6mXtgwclRQVNIjOCQK3Q7WkLQrvM9lYbGI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Q/UShqqVDOUSNYBrR1G/1X1s+YXEVXEJzeXmYvfYIr0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "uEWWDBwFW+/BpTCvNCLW7AP98hndBukzSbrwCb7sooo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MZi48DJZOgRbE0ZStR66omv6Ez1Wkjvf2D/41q6Nd0I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Go9GXHI6SCQo2QKMxkAkgYLhfo3XrVjWLR2nE2AvYyk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "P9RgE4RMQT/aHap2oICpwpgKeBAwxPUwuU9zIffKFNM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "1+EkFYvTDmz4WQRbK+kznRHoaZVLludtkDrMuM6h++E=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "QEMDwUVoyJT7MNfOYKa25xU+Lnsz/ciH8rFUri4diLI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "lUMCRAeu47BsOhNvCQTQJQeB68z0/VaElC9j5gDt9y8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VnAr7ZIjvUXpWmzbkt8skHp0oRNc3V89SfvgaZydwfw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "u4GEbsk9IEF56V1am5dRtAWXz4iFQkO03FVL87BZXIM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BaaCxmYHKJ6obIzTCdRtjw1cc8d2mUJcMbLWCjf1aLo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "N3K5kDdfcKJurfaa6s2zfKgtYvz1Pagz7VWi9ZfX8yM=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "DsTbM0AgHfhSUKvOGkxudDOY3ojYT6bifhpelqHs8+s=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j9be+ddLChInrFz6/820/uYh4WZBzlp61klyJBDy/ZY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xi7nIgj4PqVXrpKLfJhcyxyVY1d3HRo72sKKPDmuU78=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2p8s/pRBZPjYWKKMlR7AOXypDzDmPo762iXlKpCwtco=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nsofE1FmSr1TiDR0gfnxfMDQ8o2pC+1NE7Oa9ceztSg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WvmTBjsCN4ueGpEdySRwsRC5knBRLfY439/e4mG+YAY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "c0i2uKsYBv8fubnI60lZIWA1y4zw1bFgsq5MmWBHKak=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "AJR2ex094A1nJEWQsZYjALWsrSl1/huGZ37z2ZsMrpg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "LSDd6ab46sHxwJSrg5YLpsPG2o6EcsZ3rDikpHzMNmI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dnFjFoTM9sP/RjQkXBK1YpYn3v5W+j0+g/OfUHS4xu8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "L0I4JoDfktbDWe0fCDL/nQlBPkF5mNgqamnM5JKJ1Uc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dPpZD53AbAMtW6sK+rTnXYe2GGGoSCNWsCtsmArLiIs=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VakMQSPBEuSC9Nwuv8WWhrZVUmH31bUR4+G6pJhkgE8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KI+kCESWD9cB8se4uxRrFVAI5viyNNUXUyMCc903yQc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8Qu1LFMt7qlZNmYQWrsXUA80aIx0rrFPPXs2s6NBdU8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WRsXnLz3gf8o4lYYeCZjAXgPU1cdmOOYPdy7aY63iIA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "R/3f7VruxWpu+2hiHlVpplTwoOou5kfQI1k/6/9H/y8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "HjSC7VkhKih6xMhudlqfaFE8ZZnP8RKJPv4iqR7RhcE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cLM/HeUFsXlnYnYod695u6NBDS0trMq8sVRdABnF7uc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Epd2FDKZwDybzT38Z7WB0y2jiLn9/2OLzmY3Zu18l6I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ENAVynNXVpj/IdYx9kCPKaPs4bWSxRIHNlmS9QiDuZQ=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j2w5BFOnZTrPN4SFpmQyfRomnUwbEbz1A+kr3z1icjo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "I2ILaY31gonxYQhlIk4PFUIN+Pk7+9dDTK1C/s+Vcb0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "3wRufybSUsTMnUeQkP74uJNDRKeM8jBLAS64T0BRfpY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2gOiMAdnIdND4cA75E7naQdyyIYDAdcjF3uO6OiEZlU=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2S8Y/vnLM3W+MYxNCxcUItIBfdZL/T4A8vRg89n0wLg=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UBTju7UZfXLVPPYb1a8gPZ69BeCv2Fho7YVo2EUbxKc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "0HqB2x6x5HzeozpHatePECw07x1UcDdSz8kQGNznnA8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "H0SIA/BU6Xj8oT5bQkvLpEITN3CqFLbMeBcQ72NZrAE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xnh8TL3BbIs9VTUenmnx6r2UAHpGCj3G9FV0mzc+mU4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "X62YB48gO2SsWGnjYxH+aGfLQcjnP+T0hnErdWZ859g=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8pfpbIxBBiu88hpxS3CeRpv7kClEjl8SwVgckDNBGlE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UuxXNPImsE5Wp+utGfJywZBHuuGE4RmL0CArc6td82w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Sl3NKLaYEgDaovqTkKVZh2ihRFbSmyVjC63wpv3ecdc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SYjCs2AlY04xdfJGPD+gyO9NZ/zQ0Lfb/TLrjgOLS68=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oI1+4FoeI/knjsjDyCJtgZPaeyKON8tCTcM9QX0BHa8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nts1nu73aBgIdSaYye4coIuE1iBNeCuTZZC8LQ37ac8=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NQX4yKpOztKrmgBhGIC5WOALOLOq3LTpbzsN4ZLXGec=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BB4a/Xh5z+dkGCRlF+pSGC3iDOoDrFse/xzQAtmxMF4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ydjx2ea+PVuChrny6X2dluJwyXta+BsNQRsgHXp8fXw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "pPGLc4NhNaehdoV2antWuyr0GmBVEG1NhD9NiSRrTi0=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VBVHOLnWGptY26J0wqXoZI2Dnu96pccMb08zlsaxPCQ=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "aUViYC2znC55sleHfmsIN9hZ45SbYPbDcYA0gVzglsc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "riYrMXBFLavmf4MU/Ly7emDlciVqfB2/zxJoRsBUlfY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "F2wCn9rKafNZsYZwoLGkSQIpr3rk86cjYyuhSjsjRaE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ugb3W6W7WL9Vc4KiSBWIaowBfpqJlzbfBSfrIqZW06A=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gJDxhwAE6GeGCKQeVaNZ5is7+7MFHXtOG0UsnguKdoA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b9RSkt+WmMxVHQExQH0IMPpnR9zDAaJwz/mv1gtyRVY=" - }, - "power": "100", - "name": "smartpesa" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "569Sb+Wpo8VFqXRi4cQhlOD9kS8uBgmJ2rntY3GLtzY=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SNwrT1B+A4g6TY7x0QzVrmVbcbl3cHXzXdD1tFHxLNo=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "K4kLogLtZxqrYSqRVJfrFm9tUG+Tc3QWXWIewnAgI9w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "TwzOJ4GcN+ZTswub4R8488SrKeWXjY/PaqCF5neXJig=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JXW8iTiWG28E05ZFJIKvCOBwI2RrH/BOBL/MluTZ6+I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A3zUdVcpj4H+HRZmRW5xixj4dzMgqD7be9GrdXcjdns=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "7RhnD9OAZEJ4SV6V3LOZ1gGWubtX25457wCQq+AYYPI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "66j9af4xDJSblMLS+mFbp7d8TaFGu0FOo+0MwEYm2lE=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8DScmobjJQmkN44K2xiZkESM/O9MJK/DqlggnIPLpso=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "4JoJuRfaANhdM1x3AWRo1/Cj9DH3VA+fi1SynzknV+w=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cCoFsZzKZ9SQZbHe4NueVObIezP6ts0tRTZ/aN96dig=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Zp4tk/ieqplJF8xMeef9HV8bYpHSY+3hJ2sH7PfCX1I=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "jj0Y/Fy8JSJR3g+PHU6Ce0ecYwHGUVJ4bVyR7WwcyLI=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "XQDVMXja3kFk5Jb47BsqJmzcDsM4lE9+r+f/J3O5Jms=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oL/QCr7LEOivyTqpGrmwVd1r+hYI2WB5+kSVzpDMxx4=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "eeImG09hOPo1W7j7lKepN/Lx6I9GGHqVBVEKmznxACc=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Abws3eXrUFAH8LeZJIcECakPL945TTmFsBlXONOUeII=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PEg/D54SoiKZ+pic0Z0RzZa/vfYNAAf4kzSc5UKXDYk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "omAzuJps8KX3/iOC1LjwkMPMH3c6tjfLXwCNWXRBdWw=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nctikQSpoLRl5kV6KarIS761QvEOZCWw6nvc48xWhic=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NrTRAbZnBqJpW9lRW6LxXxE7EV++y7WiIRV0ifRLovA=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "W0rP8sv4Ae/LZOqlBA9evvYARDt79WpFaI26jw/9Tfk=" - }, - "power": "100", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JdfJDlE46456GWp+AkSZhzlkUQI41f8aX7611oiWUSc=" - }, - "power": "100", - "name": "" - } - ], - "app_hash": "", - "app_state": { - "accounts": [ - { - "address": "cosmosaccaddr1c2dkaym4teqw6jl9jkq8eu8nf4wzn2lgf4ydyt", - "coins": [ - { - "denom": "faucetToken", - "amount": "10000000" - }, - { - "denom": "steak", - "amount": "10000000" - } - ] - }, - { - "address": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "coins": [ - { - "denom": "jlandrewsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "coins": [ - { - "denom": "jackToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "coins": [ - { - "denom": "luigi001Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "coins": [ - { - "denom": "irisToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "coins": [ - { - "denom": "TropicalMongoXToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "coins": [ - { - "denom": "wingmanToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "coins": [ - { - "denom": "Nemea7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "coins": [ - { - "denom": "infinite-castingToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "coins": [ - { - "denom": "cwgoesToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "coins": [ - { - "denom": "lunamintToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "coins": [ - { - "denom": "skoed-validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "coins": [ - { - "denom": "starfishToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "coins": [ - { - "denom": "jjangg96Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "coins": [ - { - "denom": "iaspirationiToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "coins": [ - { - "denom": "21e800Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "coins": [ - { - "denom": "spptest1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "coins": [ - { - "denom": "windmillToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "coins": [ - { - "denom": "pbostrom/Mythos-1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "coins": [ - { - "denom": "BarytToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "coins": [ - { - "denom": "P2P.ORG ValidatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "coins": [ - { - "denom": "oleary-labsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "coins": [ - { - "denom": "wancloudsentryToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "coins": [ - { - "denom": "space4Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "coins": [ - { - "denom": "colony-finderToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "coins": [ - { - "denom": "sparkpool-validator-02Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "coins": [ - { - "denom": "mining-shipToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "coins": [ - { - "denom": "StakedToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "coins": [ - { - "denom": "nyliraToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "coins": [ - { - "denom": "liangpingToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "coins": [ - { - "denom": "SVNode01Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "coins": [ - { - "denom": "vhxnode1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "coins": [ - { - "denom": "gregToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "coins": [ - { - "denom": "bucksterToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "coins": [ - { - "denom": "grass-fedToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "coins": [ - { - "denom": "ATEAM1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "coins": [ - { - "denom": "BFF-Validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "coins": [ - { - "denom": "redbricks7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "coins": [ - { - "denom": "kittyfishToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "coins": [ - { - "denom": "ForboleToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "coins": [ - { - "denom": "coinoneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "coins": [ - { - "denom": "bmen-companyToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "coins": [ - { - "denom": "2400bpsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "coins": [ - { - "denom": "devToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "coins": [ - { - "denom": "w1m3lToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "coins": [ - { - "denom": "aetherToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "coins": [ - { - "denom": "JColToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "coins": [ - { - "denom": "SaiKrishnaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "coins": [ - { - "denom": "UmbrellaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "coins": [ - { - "denom": "@MarceldeveloperToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "coins": [ - { - "denom": "stereo-watcherToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "coins": [ - { - "denom": "cosmosToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "coins": [ - { - "denom": "stake.zoneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "coins": [ - { - "denom": "firstblock.ioToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "coins": [ - { - "denom": "shensiToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "coins": [ - { - "denom": "figmentToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "coins": [ - { - "denom": "iqlusionToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "coins": [ - { - "denom": "cosmosthecatToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "coins": [ - { - "denom": "snaticoToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "coins": [ - { - "denom": "mpaxeNodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "coins": [ - { - "denom": "joltz-secureware.ioToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "coins": [ - { - "denom": "mwnode1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "coins": [ - { - "denom": "VNode01Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "coins": [ - { - "denom": "7768Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "coins": [ - { - "denom": "block3.communityToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "coins": [ - { - "denom": "4455Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "coins": [ - { - "denom": "dooroomeeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "coins": [ - { - "denom": "sheiudToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "coins": [ - { - "denom": "Staking Facilities ValidatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "coins": [ - { - "denom": "ritter-rammToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "coins": [ - { - "denom": "meteor-discoverToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "coins": [ - { - "denom": "COSMODROMEToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "coins": [ - { - "denom": "broadleaf7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "coins": [ - { - "denom": "ravenclubToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "coins": [ - { - "denom": "dokia-capitalToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "coins": [ - { - "denom": "chainflow08Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "coins": [ - { - "denom": "MiaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "coins": [ - { - "denom": "sikka.techToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "coins": [ - { - "denom": "certus.oneToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "coins": [ - { - "denom": "Gold2Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "coins": [ - { - "denom": "idoor7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "coins": [ - { - "denom": "ironforkToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "coins": [ - { - "denom": "sunny-mintorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "coins": [ - { - "denom": "BlissDynamicsToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "coins": [ - { - "denom": "smartpesaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "coins": [ - { - "denom": "ianstreamToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "coins": [ - { - "denom": "TruNodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "coins": [ - { - "denom": "abcinToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "coins": [ - { - "denom": "kochacolajToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "coins": [ - { - "denom": "D2R-validator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "coins": [ - { - "denom": "juelianshanaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "coins": [ - { - "denom": "lambda-mixerToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "coins": [ - { - "denom": "bkcmToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "coins": [ - { - "denom": "ramihanToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "coins": [ - { - "denom": "davinchcodeToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "coins": [ - { - "denom": "DoriToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "coins": [ - { - "denom": "daefreecaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "coins": [ - { - "denom": "nuevaxToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "coins": [ - { - "denom": "inschain_validatorToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "coins": [ - { - "denom": "gruberxToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "coins": [ - { - "denom": "meleatrustToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "coins": [ - { - "denom": "Cosmodator-7000Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "coins": [ - { - "denom": "bharvestToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "coins": [ - { - "denom": "cryptiumToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "coins": [ - { - "denom": "finalityToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "coins": [ - { - "denom": "coscloudToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "coins": [ - { - "denom": "xiaochinaToken", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - }, - { - "address": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "coins": [ - { - "denom": "gazua1Token", - "amount": "1000" - }, - { - "denom": "steak", - "amount": "50" - } - ] - } - ], - "stake": { - "pool": { - "loose_tokens": "16050", - "bonded_tokens": "0", - "inflation_last_time": "0", - "inflation": "7/100", - "date_last_commission_reset": "0", - "prev_bonded_shares": "0" - }, - "params": { - "inflation_rate_change": "13/100", - "inflation_max": "1/5", - "inflation_min": "7/100", - "goal_bonded": "67/100", - "unbonding_time": "86400", - "max_validators": 128, - "bond_denom": "steak" - }, - "validators": [ - { - "owner": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MRCeBDANSjH6IsxO0z6tRe+xqoZvIGhdfl1t+SXGUpM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jlandrews", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "tOEqjO2t51PEgO9Tv0B7qM0yPmy1n5tMa3Beg0tp3ns=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jack", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "S8s6fdAQNQ3bN9SNVAsHB/j8uv1CM1roxeLesL+fh4g=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "luigi001", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2JoNf1gavJ1d6XFIumO1Mki5GVMOcg58AioHksU3maE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iris", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "k3YLQYEN2QMP6XITRsBmgb+pNGhJ5Jbg0bzUW977kK0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "TropicalMongoX", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "EREUrXXl1OJqLQag0P4h6vJ2H+8GEwyNAjgn1XEJU+I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "wingman", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "heNintBalqaJwCOjLb9+mX/cQ1ytMlV7ZroPIlkwZqo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Nemea7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nb2oRB12DlEQkFn7KSjSVkj5rDoSTsuBFa09+gmNJ7o=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "infinite-casting", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "bZSEBDNIOr0xJ/PxaAScJIyG6hqFtryBAMNwghAOTTU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cwgoes", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8K3clCjVU33BTIpUhdahGmu++WxHj4NUE9krCRkk++s=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "lunamint", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RBuRRNEzA9RA1Wrdi9PPFQJ29/n/bqN9O2tQv9Gq248=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "skoed-validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "RwPRoiY5C0covekqbr3VrQwxWGHioUUIf2+TOq8LIC0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "starfish", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2qtEBT+Tc+SD2wJsdrVMHXrBKfvesxtmtSKDK5fXwA0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "jjangg96", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gU5mmVLUSzn/fIEMgiiB4LARRoWlqjUGHr3A4SndWO8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iaspirationi", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "xlO2cnii42KisAn8OcstC/3XV5+I0FlcSbWuyy5MVA8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "21e800", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "q5ezDn4DcWFPWvMayPJI35nXr//jjF8fGHsuiHjpDcU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "spptest1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PSqbJOwglJb1yrj3aWebBpXb2ujXcR037s1Cyj2HoW4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "windmill", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A6GzeXUM3vsXaDAEYMSDgSKkqn9AoUYjs8empH46MGY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "pbostrom/Mythos-1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "81fx09BivOOxeGL7QisF8aKRZjjcARpiSaCOX9mJfY8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Baryt", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UjTvuOew2EaooduJBiYmBWeF5ai0yFJG8uio5YXpJgg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "P2P.ORG Validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "y7p9JSVZBnRxjAI9v5Pxl37hMtyuHf6B4Ghqzm6+ii0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "oleary-labs", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oG8Q5o+SN4wqMLvlIfVgQPnsQzNEKeH0D/XGM8JlGrY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "wancloudsentry", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PxJbo5FKA6mXtgwclRQVNIjOCQK3Q7WkLQrvM9lYbGI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "space4", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Q/UShqqVDOUSNYBrR1G/1X1s+YXEVXEJzeXmYvfYIr0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "colony-finder", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "uEWWDBwFW+/BpTCvNCLW7AP98hndBukzSbrwCb7sooo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sparkpool-validator-02", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "MZi48DJZOgRbE0ZStR66omv6Ez1Wkjvf2D/41q6Nd0I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mining-ship", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Go9GXHI6SCQo2QKMxkAkgYLhfo3XrVjWLR2nE2AvYyk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Staked", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "P9RgE4RMQT/aHap2oICpwpgKeBAwxPUwuU9zIffKFNM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "nylira", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "1+EkFYvTDmz4WQRbK+kznRHoaZVLludtkDrMuM6h++E=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "liangping", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "QEMDwUVoyJT7MNfOYKa25xU+Lnsz/ciH8rFUri4diLI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "SVNode01", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "lUMCRAeu47BsOhNvCQTQJQeB68z0/VaElC9j5gDt9y8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "vhxnode1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VnAr7ZIjvUXpWmzbkt8skHp0oRNc3V89SfvgaZydwfw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "greg", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "u4GEbsk9IEF56V1am5dRtAWXz4iFQkO03FVL87BZXIM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "buckster", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BaaCxmYHKJ6obIzTCdRtjw1cc8d2mUJcMbLWCjf1aLo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "grass-fed", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "N3K5kDdfcKJurfaa6s2zfKgtYvz1Pagz7VWi9ZfX8yM=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ATEAM1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "DsTbM0AgHfhSUKvOGkxudDOY3ojYT6bifhpelqHs8+s=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "BFF-Validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j9be+ddLChInrFz6/820/uYh4WZBzlp61klyJBDy/ZY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "redbricks7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xi7nIgj4PqVXrpKLfJhcyxyVY1d3HRo72sKKPDmuU78=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "kittyfish", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2p8s/pRBZPjYWKKMlR7AOXypDzDmPo762iXlKpCwtco=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Forbole", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nsofE1FmSr1TiDR0gfnxfMDQ8o2pC+1NE7Oa9ceztSg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "coinone", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WvmTBjsCN4ueGpEdySRwsRC5knBRLfY439/e4mG+YAY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bmen-company", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "c0i2uKsYBv8fubnI60lZIWA1y4zw1bFgsq5MmWBHKak=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "2400bps", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "AJR2ex094A1nJEWQsZYjALWsrSl1/huGZ37z2ZsMrpg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dev", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "LSDd6ab46sHxwJSrg5YLpsPG2o6EcsZ3rDikpHzMNmI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "w1m3l", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dnFjFoTM9sP/RjQkXBK1YpYn3v5W+j0+g/OfUHS4xu8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "aether", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "L0I4JoDfktbDWe0fCDL/nQlBPkF5mNgqamnM5JKJ1Uc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "JCol", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "dPpZD53AbAMtW6sK+rTnXYe2GGGoSCNWsCtsmArLiIs=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "SaiKrishna", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VakMQSPBEuSC9Nwuv8WWhrZVUmH31bUR4+G6pJhkgE8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Umbrella", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KI+kCESWD9cB8se4uxRrFVAI5viyNNUXUyMCc903yQc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "@Marceldeveloper", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8Qu1LFMt7qlZNmYQWrsXUA80aIx0rrFPPXs2s6NBdU8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "stereo-watcher", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "WRsXnLz3gf8o4lYYeCZjAXgPU1cdmOOYPdy7aY63iIA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cosmos", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "R/3f7VruxWpu+2hiHlVpplTwoOou5kfQI1k/6/9H/y8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "stake.zone", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "HjSC7VkhKih6xMhudlqfaFE8ZZnP8RKJPv4iqR7RhcE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "firstblock.io", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cLM/HeUFsXlnYnYod695u6NBDS0trMq8sVRdABnF7uc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "shensi", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Epd2FDKZwDybzT38Z7WB0y2jiLn9/2OLzmY3Zu18l6I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "figment", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ENAVynNXVpj/IdYx9kCPKaPs4bWSxRIHNlmS9QiDuZQ=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "iqlusion", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "j2w5BFOnZTrPN4SFpmQyfRomnUwbEbz1A+kr3z1icjo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "cosmosthecat", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "I2ILaY31gonxYQhlIk4PFUIN+Pk7+9dDTK1C/s+Vcb0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "snatico", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "3wRufybSUsTMnUeQkP74uJNDRKeM8jBLAS64T0BRfpY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mpaxeNode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2gOiMAdnIdND4cA75E7naQdyyIYDAdcjF3uO6OiEZlU=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "joltz-secureware.io", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "2S8Y/vnLM3W+MYxNCxcUItIBfdZL/T4A8vRg89n0wLg=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "mwnode1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "kol7Gj60Fct4X8T1rHLJQ0z/b14UqqSae8h1e37rLL8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "VNode01", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UBTju7UZfXLVPPYb1a8gPZ69BeCv2Fho7YVo2EUbxKc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "7768", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "0HqB2x6x5HzeozpHatePECw07x1UcDdSz8kQGNznnA8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "block3.community", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "H0SIA/BU6Xj8oT5bQkvLpEITN3CqFLbMeBcQ72NZrAE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "4455", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Xnh8TL3BbIs9VTUenmnx6r2UAHpGCj3G9FV0mzc+mU4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dooroomee", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "X62YB48gO2SsWGnjYxH+aGfLQcjnP+T0hnErdWZ859g=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sheiud", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8pfpbIxBBiu88hpxS3CeRpv7kClEjl8SwVgckDNBGlE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Staking Facilities Validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "UuxXNPImsE5Wp+utGfJywZBHuuGE4RmL0CArc6td82w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ritter-ramm", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Sl3NKLaYEgDaovqTkKVZh2ihRFbSmyVjC63wpv3ecdc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "meteor-discover", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SYjCs2AlY04xdfJGPD+gyO9NZ/zQ0Lfb/TLrjgOLS68=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "COSMODROME", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oI1+4FoeI/knjsjDyCJtgZPaeyKON8tCTcM9QX0BHa8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "broadleaf7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nts1nu73aBgIdSaYye4coIuE1iBNeCuTZZC8LQ37ac8=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ravenclub", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NQX4yKpOztKrmgBhGIC5WOALOLOq3LTpbzsN4ZLXGec=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "dokia-capital", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "BB4a/Xh5z+dkGCRlF+pSGC3iDOoDrFse/xzQAtmxMF4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "chainflow08", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ydjx2ea+PVuChrny6X2dluJwyXta+BsNQRsgHXp8fXw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Mia", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "pPGLc4NhNaehdoV2antWuyr0GmBVEG1NhD9NiSRrTi0=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sikka.tech", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "VBVHOLnWGptY26J0wqXoZI2Dnu96pccMb08zlsaxPCQ=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "certus.one", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "aUViYC2znC55sleHfmsIN9hZ45SbYPbDcYA0gVzglsc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Gold2", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "riYrMXBFLavmf4MU/Ly7emDlciVqfB2/zxJoRsBUlfY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "idoor7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "F2wCn9rKafNZsYZwoLGkSQIpr3rk86cjYyuhSjsjRaE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ironfork", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "ugb3W6W7WL9Vc4KiSBWIaowBfpqJlzbfBSfrIqZW06A=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "sunny-mintor", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "gJDxhwAE6GeGCKQeVaNZ5is7+7MFHXtOG0UsnguKdoA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "BlissDynamics", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b9RSkt+WmMxVHQExQH0IMPpnR9zDAaJwz/mv1gtyRVY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "smartpesa", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "569Sb+Wpo8VFqXRi4cQhlOD9kS8uBgmJ2rntY3GLtzY=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ianstream", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "SNwrT1B+A4g6TY7x0QzVrmVbcbl3cHXzXdD1tFHxLNo=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "TruNode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "K4kLogLtZxqrYSqRVJfrFm9tUG+Tc3QWXWIewnAgI9w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "abcin", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "TwzOJ4GcN+ZTswub4R8488SrKeWXjY/PaqCF5neXJig=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "kochacolaj", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JXW8iTiWG28E05ZFJIKvCOBwI2RrH/BOBL/MluTZ6+I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "D2R-validator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "A3zUdVcpj4H+HRZmRW5xixj4dzMgqD7be9GrdXcjdns=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "juelianshana", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "7RhnD9OAZEJ4SV6V3LOZ1gGWubtX25457wCQq+AYYPI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "lambda-mixer", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "66j9af4xDJSblMLS+mFbp7d8TaFGu0FOo+0MwEYm2lE=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bkcm", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "8DScmobjJQmkN44K2xiZkESM/O9MJK/DqlggnIPLpso=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "ramihan", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "4JoJuRfaANhdM1x3AWRo1/Cj9DH3VA+fi1SynzknV+w=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "davinchcode", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "cCoFsZzKZ9SQZbHe4NueVObIezP6ts0tRTZ/aN96dig=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Dori", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Zp4tk/ieqplJF8xMeef9HV8bYpHSY+3hJ2sH7PfCX1I=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "daefreeca", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "jj0Y/Fy8JSJR3g+PHU6Ce0ecYwHGUVJ4bVyR7WwcyLI=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "nuevax", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "XQDVMXja3kFk5Jb47BsqJmzcDsM4lE9+r+f/J3O5Jms=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "inschain_validator", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "oL/QCr7LEOivyTqpGrmwVd1r+hYI2WB5+kSVzpDMxx4=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "gruberx", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "eeImG09hOPo1W7j7lKepN/Lx6I9GGHqVBVEKmznxACc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "meleatrust", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "Abws3eXrUFAH8LeZJIcECakPL945TTmFsBlXONOUeII=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Cosmodator-7000", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "PEg/D54SoiKZ+pic0Z0RzZa/vfYNAAf4kzSc5UKXDYk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "bharvest", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "omAzuJps8KX3/iOC1LjwkMPMH3c6tjfLXwCNWXRBdWw=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "Adrian Brink - Cryptium Labs", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "nctikQSpoLRl5kV6KarIS761QvEOZCWw6nvc48xWhic=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "finality", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "NrTRAbZnBqJpW9lRW6LxXxE7EV++y7WiIRV0ifRLovA=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "coscloud", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "W0rP8sv4Ae/LZOqlBA9evvYARDt79WpFaI26jw/9Tfk=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "xiaochina", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - }, - { - "owner": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "JdfJDlE46456GWp+AkSZhzlkUQI41f8aX7611oiWUSc=" - }, - "revoked": false, - "status": 0, - "tokens": "100", - "delegator_shares": "100", - "description": { - "moniker": "gazua1", - "identity": "", - "website": "", - "details": "" - }, - "bond_height": "0", - "bond_intra_tx_counter": 0, - "proposer_reward_pool": [], - "commission": "0", - "commission_max": "0", - "commission_change_rate": "0", - "commission_change_today": "0", - "prev_bonded_tokens": "0" - } - ], - "bonds": [ - { - "delegator_addr": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "validator_addr": "cosmosaccaddr157mg9hnhchfrqvk3enrvmvj29yhmlwf759xrgw", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "validator_addr": "cosmosaccaddr193vn0gk3nsmjkxwz78gce8e8mkmagmvulpg5jt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "validator_addr": "cosmosaccaddr16rcrnftjyl2mctz78825ng8tx5ss22jf6jcp9l", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "validator_addr": "cosmosaccaddr1shuqhpl273t96yg6nnqvyfeewj3ew3mdcwvcnu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "validator_addr": "cosmosaccaddr1syhzpjwx6vv3erv2myq7txrjhrp95hrhgcl242", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "validator_addr": "cosmosaccaddr1uga4nuresex5u8ajjh2pcr39l0s9hszdkp843j", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "validator_addr": "cosmosaccaddr12wnqvqg79s9jqrul0lva3h72rfmewm7jprrcp5", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "validator_addr": "cosmosaccaddr1lq0mvtgnwe8mp0096un0v8ztcsj8ad92t2cwrq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "validator_addr": "cosmosaccaddr14e774gfzt5l9ka766ehfgu6n5hgy9f3sehzyv8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "validator_addr": "cosmosaccaddr164jntjfk9zs8x29mc27qansfwvjqs60gj6ermu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "validator_addr": "cosmosaccaddr1qkc3tghc3fms7eye7vtu0g0370epr4jkje2ne7", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "validator_addr": "cosmosaccaddr18m09d56pg5p2660de4sjfezpd8ud6jfghndfnt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "validator_addr": "cosmosaccaddr1k9pqxd8fxqlk52uwfxnlsexqj6xnmw5swhss45", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "validator_addr": "cosmosaccaddr13q937pwglh24knwa2v23ml0kkpl9vwzjmfmj3q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "validator_addr": "cosmosaccaddr1xvt4e7xd0j9dwv2w83g50tpcltsl90h5dfnz6h", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "validator_addr": "cosmosaccaddr1nnyel6v0kx8zmfh9edmre3ua4dt9306cfxsxgd", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "validator_addr": "cosmosaccaddr13cds7hwqyq9ja2hsv4sg7glq9arlk43gcl3cek", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "validator_addr": "cosmosaccaddr1y2z20pwqu5qpclque3pqkguruvheum2djtzjw3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "validator_addr": "cosmosaccaddr1anuuffusmq5ng3rhlndhnacy45et30jqygtn67", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "validator_addr": "cosmosaccaddr1wk0t6na230vxhf6ddresw2c40k5y3ayrww0s2m", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "validator_addr": "cosmosaccaddr12pn4p6r5wjpsep9kn655ng7fh59yez7t0rahru", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "validator_addr": "cosmosaccaddr15rrxdflhq4744qt9m5ysstq3zpykhacf908eez", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "validator_addr": "cosmosaccaddr17rqsh3fw6rehnwzarz90jkqtt5fupmh50gy556", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "validator_addr": "cosmosaccaddr1g4q87u438qdh2c8ue4dzdr9ldrqrs77ptm9c70", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "validator_addr": "cosmosaccaddr1dq7jt3pn7mrce2twac907jue7hjd0p0rgt3qnq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "validator_addr": "cosmosaccaddr1gg6natrtt5lf02xwr06ujcczvavl54wgljuaut", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "validator_addr": "cosmosaccaddr1zds6r7jyxyxcpf05r5yyyy3u8q2rvj9kkc6vcv", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "validator_addr": "cosmosaccaddr1l0qw5znfd6e8pshpjvyghjjzyr4l6ymla080lt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "validator_addr": "cosmosaccaddr1rxxcpkmsngd0azkh3n2467m66ls4rwq52yuv27", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "validator_addr": "cosmosaccaddr1jsch8k385shvse6j5dfx20483qym5uhq76xpjf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "validator_addr": "cosmosaccaddr19uhnhct0p45ek6qxp3cjjrjtz4pacwcsgzvpuj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "validator_addr": "cosmosaccaddr1gghhdtx2sceafvgg8dry5sqrvc8srxghm4qqsy", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "validator_addr": "cosmosaccaddr1cyayv35tv47t829mel6jm0vqzmrdhf3jq87tqg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "validator_addr": "cosmosaccaddr126ayk3hse5zvk9gxfmpsjr9565ef72pv9g20yx", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "validator_addr": "cosmosaccaddr1fskmzyt2hr8usr3s65dq3rfur3fy6g2hjp23tm", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "validator_addr": "cosmosaccaddr1lhjta6nt0lewj05m8444tuyhalkrffgpm7njpp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "validator_addr": "cosmosaccaddr1pm0gx3lk46gf8vyj5my9w5tk06cuq66ll77ugj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "validator_addr": "cosmosaccaddr15w2rengajq9js8hu57kjw88dly5vy7gsqedn0n", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "validator_addr": "cosmosaccaddr10505nl7yftsme9jk2glhjhta7w0475uva87paj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "validator_addr": "cosmosaccaddr18z3pnjgdtt337z8g5drfts7r3fm6n9a0896h0r", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "validator_addr": "cosmosaccaddr1vmdgku2g0n5p2ef995r4fugu99ze9e5me9kh4d", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "validator_addr": "cosmosaccaddr1j2frwt2vq2xer7f060wpsu3y3f63uys2w9lx2e", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "validator_addr": "cosmosaccaddr1whxd48da3r56n8eecym8zg0c6xmf35fn2myart", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "validator_addr": "cosmosaccaddr1jkmn6asju47zuuzrf8rjt7sllaj5cx4kueyv8p", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "validator_addr": "cosmosaccaddr120skmenn2a0ra8y6zassrxvnfc5rlme8rqarvs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "validator_addr": "cosmosaccaddr1jtt6al0acr8h0uvq489rt9zx9lnau7rlcu30pt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "validator_addr": "cosmosaccaddr135dz5hdtvk3z8vl0zyy5l223kjanv0gudu4905", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "validator_addr": "cosmosaccaddr182ujqw3r8p5fffjqkf0rxzj29pg5q96nxd2khq", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "validator_addr": "cosmosaccaddr1qrc3ed8tnz6vc24ftmnht8efs5ufhjmrjkds4x", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "validator_addr": "cosmosaccaddr1swydkj5u3jd4jwe7uygu4479zgs4qg6v4ds3c9", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "validator_addr": "cosmosaccaddr1l9jt8xgejkcm4sulhwj8c83ftprz5p9lyq4605", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "validator_addr": "cosmosaccaddr128ty3kzhcepjacu4q0xjgq60qa3zz8na3jl793", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "validator_addr": "cosmosaccaddr1e3qm8jd9357zhdemwnaafmf0wy3f4yqmd307c2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "validator_addr": "cosmosaccaddr18wfz5vj26y079surms5sm6avjtezzspfvqs6g4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "validator_addr": "cosmosaccaddr1vrc7zpg5teawwuzkfh6t7c6sy353sukhlarxpa", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "validator_addr": "cosmosaccaddr1umaajfgap5ef6yxvk5706kwk8j08l7wh6h9fp2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "validator_addr": "cosmosaccaddr1670l5up6e5fddvlc027yvvlvedrzyx0mmsl622", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "validator_addr": "cosmosaccaddr1wx33m9dvglryga0saey0pr99ja0klhcfrwaw7l", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "validator_addr": "cosmosaccaddr15u9ve7fz8fqaf7r2u3p4f9ru4ze47pau5cxgcg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "validator_addr": "cosmosaccaddr1h4q0xkdg30cl9vw0u8ejm0rs337dszy98gnd4a", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "validator_addr": "cosmosaccaddr12zpkulxv7kn59sgf0tpf24qhqzxsvf3gamkl7g", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "validator_addr": "cosmosaccaddr1g6sc5t9t68vmcj3alk7dfqr54tvastpxac28k6", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "validator_addr": "cosmosaccaddr1jck6gp4mqy33sk6a0fr5c8maq53hf4245v3mgg", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "validator_addr": "cosmosaccaddr1jh3grawl62juvx5p8fz5xsy9hpw8w3mngqafe4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "validator_addr": "cosmosaccaddr17nlusdvrk34fq65jemy3umfjfwaxfzv4asyl60", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "validator_addr": "cosmosaccaddr18u2sqnuetfnkugp59e9pgyv2dpuvkkxmmsc7m8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "validator_addr": "cosmosaccaddr1xdp4pls4ryvchq2n8v0cpmtwsprvyh8wvg563q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "validator_addr": "cosmosaccaddr1pmntq5en2rgtr5rzr4e304efrve4lr43z32y5s", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "validator_addr": "cosmosaccaddr197p65z7ge5g55r68thvw4l5e43gnm70jhu5g75", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "validator_addr": "cosmosaccaddr15klp8pypkd8htppzt6pguej57yyvp5p442khcu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "validator_addr": "cosmosaccaddr1jsvgewy7h62v3q43m0l347wlcwyhd4un5q8aa3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "validator_addr": "cosmosaccaddr192yhf7f7f9304cy6cu6np3r8a3m9yqzqfeu9je", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "validator_addr": "cosmosaccaddr1pag7xgpl8njlaksvp2ur5un3htg85vcrxcp5rs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "validator_addr": "cosmosaccaddr1p56gv748xfd74qek5e637vhcr6tyjd9ukqfecc", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "validator_addr": "cosmosaccaddr1kwftgznylzerft2ksgkzvvfn5rfpy4nk2ye8na", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "validator_addr": "cosmosaccaddr1rj74vaqm0xkxl5cjjam63mayh4x6at3m379ulv", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "validator_addr": "cosmosaccaddr1zpx36km7tk5cksyzxgvcp6g552p3uhwx84r53q", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "validator_addr": "cosmosaccaddr1gq0qecxs8xdaarrqxxazwavwxm7qz5jzs5anvt", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "validator_addr": "cosmosaccaddr1cypmdvszcd9kd3jenmqxd03cpceql8rtuvxftp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "validator_addr": "cosmosaccaddr1klslzz2n2nqvdaa6gwflwpka7gc60vvmh3k450", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "validator_addr": "cosmosaccaddr1qkllv8f6qakkw3hk9dqvytys090lk6twsyv8vf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "validator_addr": "cosmosaccaddr1wf9nug554ugpw4t0wnlppxc6crl2n02qr8v3cd", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "validator_addr": "cosmosaccaddr1t3afuz2kt99jz4pe5k4vjvkdmldn2x0lqzv83w", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "validator_addr": "cosmosaccaddr14zfph0h8rexsca6gg6jkwqup3sgl6mwj6eu4e6", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "validator_addr": "cosmosaccaddr1998p0xkdwvul952ydavnx88tmwkhlfa0vhrngj", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "validator_addr": "cosmosaccaddr1jw554408yw2h438q200jyuqgln76xh4ax0q4s0", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "validator_addr": "cosmosaccaddr1mwmcpq5nhaen8zyy86mrrept2gmp0z5peapkhu", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "validator_addr": "cosmosaccaddr1emaa7mwgpnpmc7yptm728ytp9quamsvu9rk4hp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "validator_addr": "cosmosaccaddr1tq0zwzyc88l2enrlhtzw0he8rm24xfd5s9aeer", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "validator_addr": "cosmosaccaddr1n9qsfp3x09rhhxptzrgmdlucqhg2ce95fm3fw8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "validator_addr": "cosmosaccaddr1sqec04r28jfevkzfkdj4ql2qzr2zwrmg78qzj8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "validator_addr": "cosmosaccaddr1hfygmryre7r8m9pfqmc85y7kw7ejphmp59k2x8", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "validator_addr": "cosmosaccaddr1jvh448tvk368k4md83ys7auledclek0vfpckz2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "validator_addr": "cosmosaccaddr1fhfcs5npydv8s96wrk9p5ychctslu92t4n5qd4", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "validator_addr": "cosmosaccaddr1eg88jsn38mrael6cqu7d2u8j6dynya7fv2p2tl", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "validator_addr": "cosmosaccaddr1ukcuqpqw3eq505wkqd2adgn8ugewxr6jtakngs", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "validator_addr": "cosmosaccaddr1na3wr7ujdp3qdej6l5y0k4znzrkaz77t2yjaqf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "validator_addr": "cosmosaccaddr1xupfqk73y7rmc6qdgv7rtjy8wsngvt2g2t59t3", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "validator_addr": "cosmosaccaddr17gvlvfpsfl6hffn5u2hahk22un4ynpykc44tat", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "validator_addr": "cosmosaccaddr1yfseqtj5sjhzz2q2ym09jym4h4nc4yevae0jp2", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "validator_addr": "cosmosaccaddr1yd0rklq45zg89fywr89ccutlcwp9kehhh0z03k", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "validator_addr": "cosmosaccaddr1arlpxs2ftf5hgetqxxkvd7mqdc28mmaqclyv4y", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "validator_addr": "cosmosaccaddr12ceualfg92x7du73mtcv0zya4nxvq3tl2m52uz", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "validator_addr": "cosmosaccaddr1wxf0ck9h2e8p2wmecxtep6cefhexsp4kzc8fxy", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "validator_addr": "cosmosaccaddr1pzlud6lg8w9phcwetc5aqp24eflshtv4xlxthf", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "validator_addr": "cosmosaccaddr10qp8kqwm2cuql0hw2az5mngpmw5xm9ee32exlp", - "shares": "100", - "height": "0" - }, - { - "delegator_addr": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "validator_addr": "cosmosaccaddr14dwnmm6n7tjdpeylpwsdsatdl0umm75dfkqcpa", - "shares": "100", - "height": "0" - } - ] - } - } -} \ No newline at end of file diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index 1f83b21bf..503c5d3fa 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -6,6 +6,6 @@ - [ ] 4. Summarize breaking API changes section under “Breaking Changes” section to the `CHANGELOG.md` to bring attention to any breaking API changes that affect RPC consumers. - [ ] 5. Tag the commit `{{ .Release.Name }}-rcN` - [ ] 6. Kick off 1 day of automated fuzz testing -- [ ] 7. Release Lead assigns 2 people to perform buddy testing script +- [ ] 7. Release Lead assigns 2 people to perform [buddy testing script](/docs/RELEASE_TEST_SCRIPT.md) and update the relevant documentation - [ ] 8. If errors are found in either #6 or #7 go back to #2 (*NOTE*: be sure to increment the `rcN`) - [ ] 9. After #6 and #7 have successfully completed then merge the release PR and push the final release tag diff --git a/docs/RELEASE_TEST_SCRIPT.md b/docs/RELEASE_TEST_SCRIPT.md new file mode 100644 index 000000000..725507958 --- /dev/null +++ b/docs/RELEASE_TEST_SCRIPT.md @@ -0,0 +1,17 @@ +This document should contain plain english instructions for testing functionality on `gaiad`. This “Script” is supposed to be run by 2 people who will each spin up a `gaiad` node and run the series of prompts below. + +- [Create a network of 2 nodes](getting-started/create-testnet.md) +- [Generate an account](sdk/clients.md) +- [Send funds from one account to the other](sdk/clients.md) +- [Create a validator](validators/validator-setup.md) +- [Edit a validator](validators/validator-setup.md) +- [Delegate to validator](sdk/clients.md) +- [Unbond from a validator](sdk/clients.md) +- [View validators and verify output](validators/validator-setup.md) +- [Query network status](getting-started/full-node.md) +- [Create a proposal](validators/validator-setup.md) +- [Query a proposal](validators/validator-setup.md) +- [Vote on a proposal](validators/validator-setup.md) +- [Query status of a proposal](validators/validator-setup.md) +- [Query the votes on a proposal](validators/validator-setup.md) +- [Export state and reload](getting-started/create-testnet.md) diff --git a/docs/getting-started/create-testnet.md b/docs/getting-started/create-testnet.md new file mode 100644 index 000000000..0b68b3287 --- /dev/null +++ b/docs/getting-started/create-testnet.md @@ -0,0 +1,27 @@ +## Create your Own Testnet + +To create your own testnet, first each validator will need to install gaiad and run gen-tx + +```bash +gaiad init gen-tx --name +``` + +This populations `$HOME/.gaiad/gen-tx/` with a json file. + +Now these json files need to be aggregated together via Github, a Google form, pastebin or other methods. + +Place all files on one computer in `$HOME/.gaiad/gen-tx/` + +```bash +gaiad init --gen-txs -o --chain= +``` + +This will generate a `genesis.json` in `$HOME/.gaiad/config/genesis.json` distribute this file to all validators on your testnet. + +### Export state + +To export state and reload (useful for testing purposes): + +``` +gaiad export > genesis.json; cp genesis.json ~/.gaiad/config/genesis.json; gaiad start +``` diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index f24f5b46d..914a6c599 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -159,5 +159,5 @@ gaiacli stake delegation \ ## Light Client Daemon ::: tip Note -🚧 We are actively working on documentation for the LCD. +🚧Documentation coming soon! ::: diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index bac2c441d..837471bf2 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -132,3 +132,132 @@ LimitNOFILE=4096 [Install] WantedBy=multi-user.target ``` + +## Delegating to a Validator + +On the upcoming mainnet, you can delegate `Atom` to a validator. These [delegators](https://cosmos.network/resources/delegators) can receive part of the validator's fee revenue. Read more about the [Cosmos Token Model](https://github.com/cosmos/cosmos/raw/master/Cosmos_Token_Model.pdf). + +### Bond Tokens + +On the testnet, we delegate `steak` instead of `Atom`. Here's how you can bond tokens to a testnet validator: + +```bash +gaiacli stake delegate \ + --amount=10steak \ + --address-delegator= \ + --address-validator= \ + --from= \ + --chain-id=gaia-7001 +``` + +While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. + +> _*NOTE:*_ Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://gaia.faucetcosmos.network/)! + +### Unbond Tokens + +If for any reason the validator misbehaves, or you want to unbond a certain amount of tokens, use this following command. You can unbond a specific amount of`shares`\(eg:`12.1`\) or all of them \(`MAX`\). + +```bash +gaiacli stake unbond \ + --address-delegator= \ + --address-validator= \ + --shares=MAX \ + --from= \ + --chain-id=gaia-7001 +``` + +You can check your balance and your stake delegation to see that the unbonding went through successfully. + +```bash +gaiacli account + +gaiacli stake delegation \ + --address-delegator= \ + --address-validator= \ + --chain-id=gaia-7001 +``` + +## Governance + +Governance is the process from which users in the Cosmos Hub can come to consensus on software upgrades, parameters of the mainnet or on custom text proposals. This is done through voting on proposals, which will be submitted by `Atom` holders on the mainnet. + +Some considerations about the voting process: + +- Voting is done by bonded `Atom` holders on a 1 bonded `Atom` 1 vote basis +- Delegators inherit the vote of their validator if they don't vote +- **Validators MUST vote on every proposal**. If a validator does not vote on a proposal, they will be **partially slashed** +- Votes are tallied at the end of the voting period (2 weeks on mainnet). Each address can vote multiple times to update its `Option` value (paying the transaction fee each time), only the last casted vote will count as valid +- Voters can choose between options `Yes`, `No`, `NoWithVeto` and `Abstain` +At the end of the voting period, a proposal is accepted if `(YesVotes/(YesVotes+NoVotes+NoWithVetoVotes))>1/2` and `(NoWithVetoVotes/(YesVotes+NoVotes+NoWithVetoVotes))<1/3`. It is rejected otherwise + +For more information about the governance process and how it works, please check out the Governance module [specification](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/governance). + +### Create a Governance proposal + +In order to create a governance proposal, you must submit an initial deposit along with the proposal details: + +- `title`: Title of the proposal +- `description`: Description of the proposal +- `type`: Type of proposal. Must be of value _Text_ (types _SoftwareUpgrade_ and _ParameterChange_ not supported yet). + +```bash +gaiacli gov submit-proposal \ + --title= \ + --description=<description> \ + --type=<Text/ParameterChange/SoftwareUpgrade> \ + --proposer=<account_cosmosaccaddr> \ + --deposit=<40steak> \ + --from=<name> \ + --chain-id=gaia-7001 +``` + + +### Increase deposit + +In order for a proposal to be broadcasted to the network, the amount deposited must be above a `minDeposit` value (default: `10 steak`). If the proposal you previously created didn't meet this requirement, you can still increase the total amount deposited to activate it. Once the minimum deposit is reached, the proposal enters voting period: + +```bash +gaiacli gov deposit \ + --proposalID=<proposal_id> \ + --depositer=<account_cosmosaccaddr> \ + --deposit=<200steak> \ + --from=<name> \ + --chain-id=gaia-7001 +``` + +> _NOTE_: Proposals that don't meet this requirement will be deleted after `MaxDepositPeriod` is reached. + +#### Query proposal + +Once created, you can now query information of the proposal: + +```bash +gaiacli gov query-proposal \ + --proposalID=<proposal_id> \ + --chain-id=gaia-7001 +``` + +### Vote on a proposal + +After a proposal's deposit reaches the `MinDeposit` value, the voting period opens. Bonded `Atom` holders can then cast vote on it: + +```bash +gaiacli gov vote \ + --proposalID=<proposal_id> \ + --voter=<account_cosmosaccaddr> \ + --option=<Yes/No/NoWithVeto/Abstain> \ + --from=<name> \ + --chain-id=gaia-7001 +``` + +#### Query vote + +Check the vote with the option you just submitted: + +```bash +gaiacli gov query-vote \ + --proposalID=<proposal_id> \ + --voter=<account_cosmosaccaddr> \ + --chain-id=gaia-7001 +``` From 0d41026a0a8aa0ca40b93d5d57e343cdef5f2830 Mon Sep 17 00:00:00 2001 From: ValarDragon <dojha12@gmail.com> Date: Mon, 13 Aug 2018 15:12:03 -0700 Subject: [PATCH 36/97] Rename transient store key to be a unique key. This caused an error with non-determinism between nodes with same gaiad version and genesis. --- PENDING.md | 3 ++- cmd/gaia/app/app.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PENDING.md b/PENDING.md index cba76aae6..eb40f8b7b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -7,7 +7,8 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * Gaia - + * Make the transient store key use a distinct store key. + * SDK * Tendermint diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 9b318c8b1..a96efa6b1 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -78,7 +78,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio keyGov: sdk.NewKVStoreKey("gov"), keyFeeCollection: sdk.NewKVStoreKey("fee"), keyParams: sdk.NewKVStoreKey("params"), - tkeyParams: sdk.NewTransientStoreKey("params"), + tkeyParams: sdk.NewTransientStoreKey("transient_params"), } // define the accountMapper From 165fdf4a07f60cf6f31b1f973c48f13fd1412a7f Mon Sep 17 00:00:00 2001 From: ValarDragon <dojha12@gmail.com> Date: Mon, 13 Aug 2018 18:26:16 -0700 Subject: [PATCH 37/97] (squash this) Add PR ref in changelog --- PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index eb40f8b7b..9f0b86a99 100644 --- a/PENDING.md +++ b/PENDING.md @@ -7,7 +7,7 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * Gaia - * Make the transient store key use a distinct store key. + * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) * SDK From f252f3e36ce07846a3edb429076cc9d734c7efcd Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk <alex@tendermint.com> Date: Tue, 14 Aug 2018 13:36:51 -0400 Subject: [PATCH 38/97] Update Cosmos signed messages ICS doc - Address PR comments - Fix markdown lint errors --- docs/ics/ics-xxx-signed-messages.md | 51 +++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 163763b62..6eeee1671 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -2,13 +2,13 @@ >TODO: Replace with valid ICS number and possibly move to new location. - * [Changelog](#changelog) - * [Abstract](#abstract) - * [Preliminary](#preliminary) - * [Specification](#specification) - * [Future Adaptations](#future-adaptations) - * [API](#api) - * [References](#references) +* [Changelog](#changelog) +* [Abstract](#abstract) +* [Preliminary](#preliminary) +* [Specification](#specification) +* [Future Adaptations](#future-adaptations) +* [API](#api) +* [References](#references) ## Status @@ -46,6 +46,7 @@ action or data, then such an application would have to either treat this as idempotent or have mechanisms in place to reject known signed messages. ## Preliminary + The Cosmos message signing protocol will be parameterized with a cryptographic secure hashing algorithm `SHA-256` and a signing algorithm `S` that contains the operations `sign` and `verify` which provide a digital signature over a set @@ -55,7 +56,7 @@ Note, our goal here is not to provide context and reasoning about why necessaril these algorithms were chosen apart from the fact they are the defacto algorithms used in Tendermint and the Cosmos SDK and that they satisfy our needs for such cryptographic algorithms such as having resistance to collision and second -pre-image attacks, as well as being deterministic and uniform. +pre-image attacks, as well as being [deterministic](https://en.wikipedia.org/wiki/Hash_function#Determinism) and [uniform](https://en.wikipedia.org/wiki/Hash_function#Uniformity). ## Specification @@ -128,6 +129,7 @@ the [JSON schema](http://json-schema.org/) specification as such: ``` e.g. + ```json { "@chain_id": "1", @@ -158,27 +160,48 @@ to expand upon it's canonical JSON structure to include such functionality. Application developers and designers should formalize a standard set of APIs that adhere to the following specification: -<hr> +----- -**cosmosSignBytes** +### **cosmosSignBytes** Params: + * `data`: the Cosmos signed message canonical JSON structure -* `address`: 20 byte account address to sign data with +* `address`: the Bech32 Cosmos account address to sign data with Returns: + * `signature`: the Cosmos signature derived using signing algorithm `S` -<hr> +----- -**cosmosSignBytesPass** +### **cosmosSignBytesPassword** Params: + * `data`: the Cosmos signed message canonical JSON structure -* `address`: 20 byte account address to sign data with +* `address`: the Bech32 Cosmos account address to sign data with * `password`: password of the account to sign data with Returns: + * `signature`: the Cosmos signature derived using signing algorithm `S` +----- + +### Examples + +Using the `secp256k1` as the DSA, `S`: + +```javascript +data = { + "@chain_id": "1", + "@type": "message", + "text": "I hereby claim I am ABC on Keybase!" +} + +cosmosSignBytes(data, "cosmosaccaddr1pvsch6cddahhrn5e8ekw0us50dpnugwnlfngt3") +> "0x7fc4a495473045022100dec81a9820df0102381cdbf7e8b0f1e2cb64c58e0ecda1324543742e0388e41a02200df37905a6505c1b56a404e23b7473d2c0bc5bcda96771d2dda59df6ed2b98f8" +``` + ## References From d9dc061b4fdc823b852bb2404837d9b7a89fa44c Mon Sep 17 00:00:00 2001 From: Rigel <rigel.rozanski@gmail.com> Date: Tue, 14 Aug 2018 20:15:02 -0400 Subject: [PATCH 39/97] Merge pull request #1819: rational -> decimal * changelog * ... * decimal func working * decimal complete, untested * fixing tests * decimal compile errors resolved * test compile errors * precision multiplier test * 1% laptop battery * fixed TestNewDecFromStr * equalities working * fix bankers round chop * ... * working, some decimal issues resolved * fix rounding error * rounding works * decimal works * ... * deleted rational * rational conversion working * revert changelog * code compiles (not tests) * went through all NewDec, made sure they were converted from NewRat properly * test debugging * all testing bugs besides the json marshalling fixed * json unmarshal * lint * document update * fix lcd test * cli test fix * mostly undo Dece -> Rate * val comments * Efficiency improvements This now caches all of the precision multipliers (as they were all used in non-mutative functions), and caches the precisionInt calculation. (Now it just copies the already calculated value) * Cache another precisionInt() call. * Improve banker rounding efficiency * remove defer, make negation in-place. * chris val comments * bez comments * Aditya comments * ... * val comments * rebasing start * ... * compiling * tests pass * cli fix * anton, cwgoes, val comments * val and jae comments * type * undo reuse quo --- PENDING.md | 1 + client/lcd/test_helpers.go | 2 +- cmd/gaia/app/genesis.go | 6 +- cmd/gaia/app/sim_test.go | 2 +- cmd/gaia/cli_test/cli_test.go | 4 +- docs/spec/governance/state.md | 18 +- docs/spec/inflation/state.md | 2 +- docs/spec/staking/end_block.md | 1 - docs/spec/staking/state.md | 30 +- docs/spec/staking/transactions.md | 12 +- examples/democoin/mock/validator.go | 18 +- .../democoin/x/assoc/validator_set_test.go | 4 +- examples/democoin/x/oracle/README.md | 2 +- examples/democoin/x/oracle/handler.go | 2 +- examples/democoin/x/oracle/keeper.go | 8 +- examples/democoin/x/oracle/oracle_test.go | 10 +- types/decimal.go | 418 ++++++++++++++++++ types/decimal_test.go | 301 +++++++++++++ types/rational.go | 262 ----------- types/rational_test.go | 402 ----------------- types/stake.go | 12 +- x/distribution/keeper.go | 4 +- x/distribution/keeper_test.go | 8 +- x/distribution/movement.go | 14 +- x/distribution/types.go | 22 +- x/gov/genesis.go | 6 +- x/gov/procedures.go | 6 +- x/gov/proposals.go | 16 +- x/gov/tally.go | 22 +- x/gov/test_common.go | 2 +- x/params/keeper.go | 12 +- x/params/keeper_test.go | 14 +- x/slashing/app_test.go | 4 +- x/slashing/handler_test.go | 2 +- x/slashing/keeper_test.go | 12 +- x/slashing/params.go | 18 +- x/slashing/test_common.go | 2 +- x/slashing/tick_test.go | 2 +- x/stake/app_test.go | 18 +- x/stake/client/cli/tx.go | 12 +- x/stake/client/rest/query.go | 2 +- x/stake/client/rest/tx.go | 5 +- x/stake/client/rest/utils.go | 2 +- x/stake/genesis_test.go | 20 +- x/stake/handler_test.go | 66 +-- x/stake/keeper/delegation.go | 10 +- x/stake/keeper/delegation_test.go | 32 +- x/stake/keeper/keeper_test.go | 2 +- x/stake/keeper/sdk_types.go | 2 +- x/stake/keeper/slash.go | 24 +- x/stake/keeper/slash_test.go | 58 +-- x/stake/keeper/test_common.go | 10 +- x/stake/keeper/validator_test.go | 100 ++--- x/stake/simulation/invariants.go | 4 +- x/stake/simulation/msgs.go | 6 +- x/stake/types/delegation.go | 14 +- x/stake/types/delegation_test.go | 18 +- x/stake/types/errors.go | 7 - x/stake/types/inflation_test.go | 65 +-- x/stake/types/msg.go | 26 +- x/stake/types/msg_test.go | 26 +- x/stake/types/params.go | 16 +- x/stake/types/pool.go | 50 +-- x/stake/types/pool_test.go | 22 +- x/stake/types/validator.go | 88 ++-- x/stake/types/validator_test.go | 79 ++-- 66 files changed, 1254 insertions(+), 1213 deletions(-) create mode 100644 types/decimal.go create mode 100644 types/decimal_test.go delete mode 100644 types/rational.go delete mode 100644 types/rational_test.go diff --git a/PENDING.md b/PENDING.md index c9df61865..4fcc0c6a9 100644 --- a/PENDING.md +++ b/PENDING.md @@ -34,6 +34,7 @@ BREAKING CHANGES * `gaiacli gov vote --voter` * [x/gov] Added tags sub-package, changed tags to use dash-case * [x/gov] Governance parameters are now stored in globalparams store +* [core] \#1807 Switch from use of rational to decimal * [lcd] \#1866 Updated lcd /slashing/signing_info endpoint to take cosmosvalpub instead of cosmosvaladdr * [types] sdk.NewCoin now takes sdk.Int, sdk.NewInt64Coin takes int64 * [cli] #1551: Officially removed `--name` from CLI commands diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index ee46b267d..818eae1e8 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -173,7 +173,7 @@ func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("steak", 100)} acc := gapp.NewGenesisAccount(&accAuth) genesisState.Accounts = append(genesisState.Accounts, acc) - genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100)) + genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewDec(100)) } appState, err := wire.MarshalJSONIndent(cdc, genesisState) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 1731fe2dc..e35b21c4b 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -185,7 +185,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState } acc := NewGenesisAccount(&accAuth) genaccs[i] = acc - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionsAcc)) // increase the supply + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionsAcc)) // increase the supply // add the validator if len(genTx.Name) > 0 { @@ -193,10 +193,10 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState validator := stake.NewValidator(genTx.Address, sdk.MustGetAccPubKeyBech32(genTx.PubKey), desc) - stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewRat(freeFermionVal)) // increase the supply + stakeData.Pool.LooseTokens = stakeData.Pool.LooseTokens.Add(sdk.NewDec(freeFermionVal)) // increase the supply // add some new shares to the validator - var issuedDelShares sdk.Rat + var issuedDelShares sdk.Dec validator, stakeData.Pool, issuedDelShares = validator.AddTokensFromDel(stakeData.Pool, freeFermionVal) stakeData.Validators = append(stakeData.Validators, validator) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index f0bea1e17..6369b4ca6 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -48,7 +48,7 @@ func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { // Default genesis state stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(1000) genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index ea4f2e47d..244a9eb83 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -132,7 +132,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) require.Equal(t, validator.Owner, barAddr) - require.True(sdk.RatEq(t, sdk.NewRat(2), validator.Tokens)) + require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens)) // unbond a single share unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) @@ -149,7 +149,7 @@ func TestGaiaCLICreateValidator(t *testing.T) { require.Equal(t, int64(9), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc) */ validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) - require.Equal(t, "1/1", validator.Tokens.String()) + require.Equal(t, "1.0000000000", validator.Tokens.String()) } func TestGaiaCLISubmitProposal(t *testing.T) { diff --git a/docs/spec/governance/state.md b/docs/spec/governance/state.md index c61fd1e3f..728ded371 100644 --- a/docs/spec/governance/state.md +++ b/docs/spec/governance/state.md @@ -25,9 +25,9 @@ type VotingProcedure struct { ```go type TallyingProcedure struct { - Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 - Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 - GovernancePenalty sdk.Rat // Penalty if validator does not vote + Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 + Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 + GovernancePenalty sdk.Dec // Penalty if validator does not vote GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply } ``` @@ -81,7 +81,7 @@ This type is used in a temp map when tallying ```go type ValidatorGovInfo struct { - Minus sdk.Rat + Minus sdk.Dec Vote Vote } ``` @@ -103,17 +103,17 @@ type Proposal struct { VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached CurrentStatus ProposalStatus // Current status of the proposal - YesVotes sdk.Rat - NoVotes sdk.Rat - NoWithVetoVotes sdk.Rat - AbstainVotes sdk.Rat + YesVotes sdk.Dec + NoVotes sdk.Dec + NoWithVetoVotes sdk.Dec + AbstainVotes sdk.Dec } ``` We also mention a method to update the tally for a given proposal: ```go - func (proposal Proposal) updateTally(vote byte, amount sdk.Rat) + func (proposal Proposal) updateTally(vote byte, amount sdk.Dec) ``` ### Stores diff --git a/docs/spec/inflation/state.md b/docs/spec/inflation/state.md index dea10c046..c16286804 100644 --- a/docs/spec/inflation/state.md +++ b/docs/spec/inflation/state.md @@ -7,7 +7,7 @@ The current annual inflation rate. ```golang -type Inflation sdk.Rat +type Inflation sdk.Dec ``` ### InflationLastTime diff --git a/docs/spec/staking/end_block.md b/docs/spec/staking/end_block.md index b40b06b92..0eb557fec 100644 --- a/docs/spec/staking/end_block.md +++ b/docs/spec/staking/end_block.md @@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges ClearTendermintUpdates() return vsc ``` - diff --git a/docs/spec/staking/state.md b/docs/spec/staking/state.md index 376a38ced..46f18ed78 100644 --- a/docs/spec/staking/state.md +++ b/docs/spec/staking/state.md @@ -13,7 +13,7 @@ type Pool struct { LooseTokens int64 // tokens not associated with any bonded validator BondedTokens int64 // reserve of bonded tokens InflationLastTime int64 // block which the last inflation was processed // TODO make time - Inflation sdk.Rat // current annual inflation rate + Inflation sdk.Dec // current annual inflation rate DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily) } @@ -28,10 +28,10 @@ overall functioning of the stake module. ```golang type Params struct { - InflationRateChange sdk.Rat // maximum annual change in inflation rate - InflationMax sdk.Rat // maximum inflation rate - InflationMin sdk.Rat // minimum inflation rate - GoalBonded sdk.Rat // Goal of percent bonded atoms + InflationRateChange sdk.Dec // maximum annual change in inflation rate + InflationMax sdk.Dec // maximum inflation rate + InflationMin sdk.Dec // minimum inflation rate + GoalBonded sdk.Dec // Goal of percent bonded atoms MaxValidators uint16 // maximum number of validators BondDenom string // bondable coin denomination @@ -74,9 +74,9 @@ type Validator struct { Revoked bool // has the validator been revoked? Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) - Tokens sdk.Rat // delegated tokens (incl. self-delegation) - DelegatorShares sdk.Rat // total shares issued to a validator's delegators - SlashRatio sdk.Rat // increases each time the validator is slashed + Tokens sdk.Dec // delegated tokens (incl. self-delegation) + DelegatorShares sdk.Dec // total shares issued to a validator's delegators + SlashRatio sdk.Dec // increases each time the validator is slashed Description Description // description terms for the validator @@ -88,10 +88,10 @@ type Validator struct { } type CommissionInfo struct { - Rate sdk.Rat // the commission rate of fees charged to any delegators - Max sdk.Rat // maximum commission rate which this validator can ever charge - ChangeRate sdk.Rat // maximum daily increase of the validator commission - ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time) + Rate sdk.Dec // the commission rate of fees charged to any delegators + Max sdk.Dec // maximum commission rate which this validator can ever charge + ChangeRate sdk.Dec // maximum daily increase of the validator commission + ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time) LastChange int64 // unix timestamp of last commission change } @@ -117,7 +117,7 @@ the transaction is the owner of the bond. ```golang type Delegation struct { - Shares sdk.Rat // delegation shares recieved + Shares sdk.Dec // delegation shares recieved Height int64 // last height bond updated } ``` @@ -178,8 +178,8 @@ the original redelegation has been completed. ```golang type Redelegation struct { - SourceShares sdk.Rat // amount of source shares redelegating - DestinationShares sdk.Rat // amount of destination shares created at redelegation + SourceShares sdk.Dec // amount of source shares redelegating + DestinationShares sdk.Dec // amount of destination shares created at redelegation CompleteTime int64 // unix time to complete redelegation } ``` diff --git a/docs/spec/staking/transactions.md b/docs/spec/staking/transactions.md index 4f2567958..d1b6a3626 100644 --- a/docs/spec/staking/transactions.md +++ b/docs/spec/staking/transactions.md @@ -18,7 +18,7 @@ Other notes: - `sender` denotes the address of the sender of the transaction - `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and modify objects from the store - - `sdk.Rat` refers to a rational numeric type specified by the SDK. + - `sdk.Dec` refers to a decimal type specified by the SDK. ### TxCreateValidator @@ -34,9 +34,9 @@ type TxCreateValidator struct { SelfDelegation coin.Coin Description Description - Commission sdk.Rat - CommissionMax sdk.Rat - CommissionMaxChange sdk.Rat + Commission sdk.Dec + CommissionMax sdk.Dec + CommissionMaxChange sdk.Dec } @@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant), ```golang type TxEditCandidacy struct { GovernancePubKey crypto.PubKey - Commission sdk.Rat + Commission sdk.Dec Description Description } @@ -199,7 +199,7 @@ type TxRedelegate struct { DelegatorAddr Address ValidatorFrom Validator ValidatorTo Validator - Shares sdk.Rat + Shares sdk.Dec CompletedTime int64 } diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 0ef0a2391..789a1cb6a 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -10,7 +10,7 @@ import ( // Validator implements sdk.Validator type Validator struct { Address sdk.AccAddress - Power sdk.Rat + Power sdk.Dec } // Implements sdk.Validator @@ -29,18 +29,18 @@ func (v Validator) GetPubKey() crypto.PubKey { } // Implements sdk.Validator -func (v Validator) GetTokens() sdk.Rat { - return sdk.ZeroRat() +func (v Validator) GetTokens() sdk.Dec { + return sdk.ZeroDec() } // Implements sdk.Validator -func (v Validator) GetPower() sdk.Rat { +func (v Validator) GetPower() sdk.Dec { return v.Power } // Implements sdk.Validator -func (v Validator) GetDelegatorShares() sdk.Rat { - return sdk.ZeroRat() +func (v Validator) GetDelegatorShares() sdk.Dec { + return sdk.ZeroDec() } // Implements sdk.Validator @@ -93,8 +93,8 @@ func (vs *ValidatorSet) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) } // TotalPower implements sdk.ValidatorSet -func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Rat { - res := sdk.ZeroRat() +func (vs *ValidatorSet) TotalPower(ctx sdk.Context) sdk.Dec { + res := sdk.ZeroDec() for _, val := range vs.Validators { res = res.Add(val.Power) } @@ -122,7 +122,7 @@ func (vs *ValidatorSet) RemoveValidator(addr sdk.AccAddress) { } // Implements sdk.ValidatorSet -func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Rat) { +func (vs *ValidatorSet) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, power int64, amt sdk.Dec) { panic("not implemented") } diff --git a/examples/democoin/x/assoc/validator_set_test.go b/examples/democoin/x/assoc/validator_set_test.go index 2fead3ad2..eac23b25e 100644 --- a/examples/democoin/x/assoc/validator_set_test.go +++ b/examples/democoin/x/assoc/validator_set_test.go @@ -32,8 +32,8 @@ func TestValidatorSet(t *testing.T) { addr2 := []byte("addr2") base := &mock.ValidatorSet{[]mock.Validator{ - {addr1, sdk.NewRat(1)}, - {addr2, sdk.NewRat(2)}, + {addr1, sdk.NewDec(1)}, + {addr2, sdk.NewDec(2)}, }} valset := NewValidatorSet(wire.NewCodec(), ctx.KVStore(key).Prefix([]byte("assoc")), base, 1, 5) diff --git a/examples/democoin/x/oracle/README.md b/examples/democoin/x/oracle/README.md index eec02d724..0cfcb820d 100644 --- a/examples/democoin/x/oracle/README.md +++ b/examples/democoin/x/oracle/README.md @@ -38,7 +38,7 @@ func NewHandler(keeper Keeper) sdk.Handler { In the previous example, the keeper has an `oracle.Keeper`. `oracle.Keeper`s are generated by `NewKeeper`. ```go -func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper { +func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper { return Keeper { cdc: cdc, key: key, diff --git a/examples/democoin/x/oracle/handler.go b/examples/democoin/x/oracle/handler.go index 079f7680f..3c78fc566 100644 --- a/examples/democoin/x/oracle/handler.go +++ b/examples/democoin/x/oracle/handler.go @@ -23,7 +23,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid // and recalculate voted power hash := ctx.BlockHeader().ValidatorsHash if !bytes.Equal(hash, info.Hash) { - info.Power = sdk.ZeroRat() + info.Power = sdk.ZeroDec() info.Hash = hash prefix := GetSignPrefix(p, keeper.cdc) store := ctx.KVStore(keeper.key) diff --git a/examples/democoin/x/oracle/keeper.go b/examples/democoin/x/oracle/keeper.go index 25554faa8..0406f560a 100644 --- a/examples/democoin/x/oracle/keeper.go +++ b/examples/democoin/x/oracle/keeper.go @@ -13,12 +13,12 @@ type Keeper struct { valset sdk.ValidatorSet - supermaj sdk.Rat + supermaj sdk.Dec timeout int64 } // NewKeeper constructs a new keeper -func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Rat, timeout int64) Keeper { +func NewKeeper(key sdk.StoreKey, cdc *wire.Codec, valset sdk.ValidatorSet, supermaj sdk.Dec, timeout int64) Keeper { if timeout < 0 { panic("Timeout should not be negative") } @@ -46,7 +46,7 @@ const ( // Info for each payload type Info struct { - Power sdk.Rat + Power sdk.Dec Hash []byte LastSigned int64 Status InfoStatus @@ -55,7 +55,7 @@ type Info struct { // EmptyInfo construct an empty Info func EmptyInfo(ctx sdk.Context) Info { return Info{ - Power: sdk.ZeroRat(), + Power: sdk.ZeroDec(), Hash: ctx.BlockHeader().ValidatorsHash, LastSigned: ctx.BlockHeight(), Status: Pending, diff --git a/examples/democoin/x/oracle/oracle_test.go b/examples/democoin/x/oracle/oracle_test.go index c476290f8..f4971c8b1 100644 --- a/examples/democoin/x/oracle/oracle_test.go +++ b/examples/democoin/x/oracle/oracle_test.go @@ -107,9 +107,9 @@ func TestOracle(t *testing.T) { addr3 := []byte("addr3") addr4 := []byte("addr4") valset := &mock.ValidatorSet{[]mock.Validator{ - {addr1, sdk.NewRat(7)}, - {addr2, sdk.NewRat(7)}, - {addr3, sdk.NewRat(1)}, + {addr1, sdk.NewDec(7)}, + {addr2, sdk.NewDec(7)}, + {addr3, sdk.NewDec(1)}, }} key := sdk.NewKVStoreKey("testkey") @@ -119,7 +119,7 @@ func TestOracle(t *testing.T) { require.Nil(t, err) ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz}) - ork := NewKeeper(key, cdc, valset, sdk.NewRat(2, 3), 100) + ork := NewKeeper(key, cdc, valset, sdk.NewDecWithPrec(667, 3), 100) // 66.7% h := seqHandler(ork, key, sdk.CodespaceRoot) // Nonmock.Validator signed, transaction failed @@ -171,7 +171,7 @@ func TestOracle(t *testing.T) { require.Equal(t, 1, getSequence(ctx, key)) // Should handle mock.Validator set change - valset.AddValidator(mock.Validator{addr4, sdk.NewRat(12)}) + valset.AddValidator(mock.Validator{addr4, sdk.NewDec(12)}) bz, err = json.Marshal(valset) require.Nil(t, err) ctx = ctx.WithBlockHeader(abci.Header{ValidatorsHash: bz}) diff --git a/types/decimal.go b/types/decimal.go new file mode 100644 index 000000000..cd5c048e3 --- /dev/null +++ b/types/decimal.go @@ -0,0 +1,418 @@ +package types + +import ( + "encoding/json" + "fmt" + "math/big" + "strconv" + "strings" + "testing" +) + +// NOTE: never use new(Dec) or else we will panic unmarshalling into the +// nil embedded big.Int +type Dec struct { + *big.Int `json:"int"` +} + +// number of decimal places +const ( + Precision = 10 + + // bytes required to represent the above precision + // ceil(log2(9999999999)) + DecimalPrecisionBits = 34 +) + +var ( + precisionReuse = new(big.Int).Exp(big.NewInt(10), big.NewInt(Precision), nil) + fivePrecision = new(big.Int).Quo(precisionReuse, big.NewInt(2)) + precisionMultipliers []*big.Int + zeroInt = big.NewInt(0) + oneInt = big.NewInt(1) + tenInt = big.NewInt(10) +) + +// Set precision multipliers +func init() { + precisionMultipliers = make([]*big.Int, Precision+1) + for i := 0; i <= Precision; i++ { + precisionMultipliers[i] = calcPrecisionMultiplier(int64(i)) + } +} + +func precisionInt() *big.Int { + return new(big.Int).Set(precisionReuse) +} + +// nolint - common values +func ZeroDec() Dec { return Dec{new(big.Int).Set(zeroInt)} } +func OneDec() Dec { return Dec{precisionInt()} } + +// calculate the precision multiplier +func calcPrecisionMultiplier(prec int64) *big.Int { + if prec > Precision { + panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec)) + } + zerosToAdd := Precision - prec + multiplier := new(big.Int).Exp(tenInt, big.NewInt(zerosToAdd), nil) + return multiplier +} + +// get the precision multiplier, do not mutate result +func precisionMultiplier(prec int64) *big.Int { + if prec > Precision { + panic(fmt.Sprintf("too much precision, maximum %v, provided %v", Precision, prec)) + } + return precisionMultipliers[prec] +} + +//______________________________________________________________________________________________ + +// create a new Dec from integer assuming whole number +func NewDec(i int64) Dec { + return NewDecWithPrec(i, 0) +} + +// create a new Dec from integer with decimal place at prec +// CONTRACT: prec <= Precision +func NewDecWithPrec(i, prec int64) Dec { + return Dec{ + new(big.Int).Mul(big.NewInt(i), precisionMultiplier(prec)), + } +} + +// create a new Dec from big integer assuming whole numbers +// CONTRACT: prec <= Precision +func NewDecFromBigInt(i *big.Int) Dec { + return NewDecFromBigIntWithPrec(i, 0) +} + +// create a new Dec from big integer assuming whole numbers +// CONTRACT: prec <= Precision +func NewDecFromBigIntWithPrec(i *big.Int, prec int64) Dec { + return Dec{ + new(big.Int).Mul(i, precisionMultiplier(prec)), + } +} + +// create a new Dec from big integer assuming whole numbers +// CONTRACT: prec <= Precision +func NewDecFromInt(i Int) Dec { + return NewDecFromIntWithPrec(i, 0) +} + +// create a new Dec from big integer with decimal place at prec +// CONTRACT: prec <= Precision +func NewDecFromIntWithPrec(i Int, prec int64) Dec { + return Dec{ + new(big.Int).Mul(i.BigInt(), precisionMultiplier(prec)), + } +} + +// create a decimal from an input decimal string. +// valid must come in the form: +// (-) whole integers (.) decimal integers +// examples of acceptable input include: +// -123.456 +// 456.7890 +// 345 +// -456789 +// +// NOTE - An error will return if more decimal places +// are provided in the string than the constant Precision. +// +// CONTRACT - This function does not mutate the input str. +func NewDecFromStr(str string) (d Dec, err Error) { + if len(str) == 0 { + return d, ErrUnknownRequest("decimal string is empty") + } + + // first extract any negative symbol + neg := false + if str[0] == '-' { + neg = true + str = str[1:] + } + + if len(str) == 0 { + return d, ErrUnknownRequest("decimal string is empty") + } + + strs := strings.Split(str, ".") + lenDecs := 0 + combinedStr := strs[0] + if len(strs) == 2 { + lenDecs = len(strs[1]) + if lenDecs == 0 || len(combinedStr) == 0 { + return d, ErrUnknownRequest("bad decimal length") + } + combinedStr = combinedStr + strs[1] + } else if len(strs) > 2 { + return d, ErrUnknownRequest("too many periods to be a decimal string") + } + + if lenDecs > Precision { + return d, ErrUnknownRequest( + fmt.Sprintf("too much precision, maximum %v, len decimal %v", Precision, lenDecs)) + } + + // add some extra zero's to correct to the Precision factor + zerosToAdd := Precision - lenDecs + zeros := fmt.Sprintf(`%0`+strconv.Itoa(zerosToAdd)+`s`, "") + combinedStr = combinedStr + zeros + + combined, ok := new(big.Int).SetString(combinedStr, 10) + if !ok { + return d, ErrUnknownRequest(fmt.Sprintf("bad string to integer conversion, combinedStr: %v", combinedStr)) + } + if neg { + combined = new(big.Int).Neg(combined) + } + return Dec{combined}, nil +} + +//______________________________________________________________________________________________ +//nolint +func (d Dec) IsZero() bool { return (d.Int).Sign() == 0 } // Is equal to zero +func (d Dec) Equal(d2 Dec) bool { return (d.Int).Cmp(d2.Int) == 0 } +func (d Dec) GT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) > 0 } // greater than +func (d Dec) GTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) >= 0 } // greater than or equal +func (d Dec) LT(d2 Dec) bool { return (d.Int).Cmp(d2.Int) < 0 } // less than +func (d Dec) LTE(d2 Dec) bool { return (d.Int).Cmp(d2.Int) <= 0 } // less than or equal +func (d Dec) Neg() Dec { return Dec{new(big.Int).Neg(d.Int)} } // reverse the decimal sign + +// addition +func (d Dec) Add(d2 Dec) Dec { + res := new(big.Int).Add(d.Int, d2.Int) + + if res.BitLen() > 255+DecimalPrecisionBits { + panic("Int overflow") + } + return Dec{res} +} + +// subtraction +func (d Dec) Sub(d2 Dec) Dec { + res := new(big.Int).Sub(d.Int, d2.Int) + + if res.BitLen() > 255+DecimalPrecisionBits { + panic("Int overflow") + } + return Dec{res} +} + +// multiplication +func (d Dec) Mul(d2 Dec) Dec { + mul := new(big.Int).Mul(d.Int, d2.Int) + chopped := chopPrecisionAndRound(mul) + + if chopped.BitLen() > 255+DecimalPrecisionBits { + panic("Int overflow") + } + return Dec{chopped} +} + +// quotient +func (d Dec) Quo(d2 Dec) Dec { + + // multiply precision twice + mul := new(big.Int).Mul(d.Int, precisionReuse) + mul.Mul(mul, precisionReuse) + + quo := new(big.Int).Quo(mul, d2.Int) + chopped := chopPrecisionAndRound(quo) + + if chopped.BitLen() > 255+DecimalPrecisionBits { + panic("Int overflow") + } + return Dec{chopped} +} + +func (d Dec) String() string { + str := d.ToLeftPaddedWithDecimals(Precision) + placement := len(str) - Precision + if placement < 0 { + panic("too few decimal digits") + } + return str[:placement] + "." + str[placement:] +} + +// TODO panic if negative or if totalDigits < len(initStr)??? +// evaluate as an integer and return left padded string +func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string { + intStr := d.Int.String() + fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s` + return fmt.Sprintf(fcode, intStr) +} + +// TODO panic if negative or if totalDigits < len(initStr)??? +// evaluate as an integer and return left padded string +func (d Dec) ToLeftPadded(totalDigits int8) string { + chopped := chopPrecisionAndRound(d.Int) + intStr := chopped.String() + fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s` + return fmt.Sprintf(fcode, intStr) +} + +// ____ +// __| |__ "chop 'em +// ` \ round!" +// ___|| ~ _ -bankers +// | | __ +// | | | __|__|__ +// |_____: / | $$$ | +// |________| + +// nolint - go-cyclo +// Remove a Precision amount of rightmost digits and perform bankers rounding +// on the remainder (gaussian rounding) on the digits which have been removed. +// +// TODO We should make this function mutate the input. The functions here +// don't need to allocate different memory for chopped after computing the +// result +func chopPrecisionAndRound(d *big.Int) *big.Int { + + // remove the negative and add it back when returning + if d.Sign() == -1 { + // make d positive, compute chopped value, and then un-mutate d + d = d.Neg(d) + d = chopPrecisionAndRound(d) + d = d.Neg(d) + return d + } + + // get the trucated quotient and remainder + quo, rem := big.NewInt(0), big.NewInt(0) + quo, rem = quo.QuoRem(d, precisionReuse, rem) + + if rem.Sign() == 0 { // remainder is zero + return quo + } + + switch rem.Cmp(fivePrecision) { + case -1: + return quo + case 1: + return quo.Add(quo, oneInt) + default: // bankers rounding must take place + // always round to an even number + if quo.Bit(0) == 0 { + return quo + } + return quo.Add(quo, oneInt) + } +} + +// RoundInt64 rounds the decimal using bankers rounding +func (d Dec) RoundInt64() int64 { + chopped := chopPrecisionAndRound(d.Int) + if !chopped.IsInt64() { + panic("Int64() out of bound") + } + return chopped.Int64() +} + +// RoundInt round the decimal using bankers rounding +func (d Dec) RoundInt() Int { + return NewIntFromBigInt(chopPrecisionAndRound(d.Int)) +} + +//___________________________________________________________________________________ + +// reuse nil values +var ( + nilAmino string + nilJSON []byte +) + +func init() { + empty := new(big.Int) + bz, err := empty.MarshalText() + if err != nil { + panic("bad nil amino init") + } + nilAmino = string(bz) + + nilJSON, err = json.Marshal(string(bz)) + if err != nil { + panic("bad nil json init") + } +} + +// wraps d.MarshalText() +func (d Dec) MarshalAmino() (string, error) { + if d.Int == nil { + return nilAmino, nil + } + bz, err := d.Int.MarshalText() + return string(bz), err +} + +// requires a valid JSON string - strings quotes and calls UnmarshalText +func (d *Dec) UnmarshalAmino(text string) (err error) { + tempInt := new(big.Int) + err = tempInt.UnmarshalText([]byte(text)) + if err != nil { + return err + } + d.Int = tempInt + return nil +} + +// MarshalJSON defines custom encoding scheme +func (d Dec) MarshalJSON() ([]byte, error) { + if d.Int == nil { + return nilJSON, nil + } + + bz, err := d.Int.MarshalText() + if err != nil { + return nil, err + } + return json.Marshal(string(bz)) +} + +// UnmarshalJSON defines custom decoding scheme +func (d *Dec) UnmarshalJSON(bz []byte) error { + if d.Int == nil { + d.Int = new(big.Int) + } + + var text string + err := json.Unmarshal(bz, &text) + if err != nil { + return err + } + return d.Int.UnmarshalText([]byte(text)) +} + +//___________________________________________________________________________________ +// helpers + +// test if two decimal arrays are equal +func DecsEqual(d1s, d2s []Dec) bool { + if len(d1s) != len(d2s) { + return false + } + + for i, d1 := range d1s { + if !d1.Equal(d2s[i]) { + return false + } + } + return true +} + +// minimum decimal between two +func MinDec(d1, d2 Dec) Dec { + if d1.LT(d2) { + return d1 + } + return d2 +} + +// intended to be used with require/assert: require.True(DecEq(...)) +func DecEq(t *testing.T, exp, got Dec) (*testing.T, bool, string, Dec, Dec) { + return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got +} diff --git a/types/decimal_test.go b/types/decimal_test.go new file mode 100644 index 000000000..115eeacb0 --- /dev/null +++ b/types/decimal_test.go @@ -0,0 +1,301 @@ +package types + +import ( + "math/big" + "testing" + + wire "github.com/cosmos/cosmos-sdk/wire" + "github.com/stretchr/testify/require" +) + +// create a decimal from a decimal string (ex. "1234.5678") +func mustNewDecFromStr(t *testing.T, str string) (d Dec) { + d, err := NewDecFromStr(str) + require.NoError(t, err) + return d +} + +//_______________________________________ + +func TestPrecisionMultiplier(t *testing.T) { + res := precisionMultiplier(5) + exp := big.NewInt(100000) + require.Equal(t, 0, res.Cmp(exp), "equality was incorrect, res %v, exp %v", res, exp) +} + +func TestNewDecFromStr(t *testing.T) { + largeBigInt, success := new(big.Int).SetString("3144605511029693144278234343371835", 10) + require.True(t, success) + tests := []struct { + decimalStr string + expErr bool + exp Dec + }{ + {"", true, Dec{}}, + {"0.-75", true, Dec{}}, + {"0", false, NewDec(0)}, + {"1", false, NewDec(1)}, + {"1.1", false, NewDecWithPrec(11, 1)}, + {"0.75", false, NewDecWithPrec(75, 2)}, + {"0.8", false, NewDecWithPrec(8, 1)}, + {"0.11111", false, NewDecWithPrec(11111, 5)}, + {"314460551102969.3144278234343371835", true, NewDec(3141203149163817869)}, + {"314460551102969314427823434337.1835718092488231350", + true, NewDecFromBigIntWithPrec(largeBigInt, 4)}, + {"314460551102969314427823434337.1835", + false, NewDecFromBigIntWithPrec(largeBigInt, 4)}, + {".", true, Dec{}}, + {".0", true, NewDec(0)}, + {"1.", true, NewDec(1)}, + {"foobar", true, Dec{}}, + {"0.foobar", true, Dec{}}, + {"0.foobar.", true, Dec{}}, + } + + for tcIndex, tc := range tests { + res, err := NewDecFromStr(tc.decimalStr) + if tc.expErr { + require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex) + } else { + require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex) + require.True(t, res.Equal(tc.exp), "equality was incorrect, res %v, exp %v, tc %v", res, tc.exp, tcIndex) + } + + // negative tc + res, err = NewDecFromStr("-" + tc.decimalStr) + if tc.expErr { + require.NotNil(t, err, "error expected, decimalStr %v, tc %v", tc.decimalStr, tcIndex) + } else { + require.Nil(t, err, "unexpected error, decimalStr %v, tc %v", tc.decimalStr, tcIndex) + exp := tc.exp.Mul(NewDec(-1)) + require.True(t, res.Equal(exp), "equality was incorrect, res %v, exp %v, tc %v", res, exp, tcIndex) + } + } +} + +func TestEqualities(t *testing.T) { + tests := []struct { + d1, d2 Dec + gt, lt, eq bool + }{ + {NewDec(0), NewDec(0), false, false, true}, + {NewDecWithPrec(0, 2), NewDecWithPrec(0, 4), false, false, true}, + {NewDecWithPrec(100, 0), NewDecWithPrec(100, 0), false, false, true}, + {NewDecWithPrec(-100, 0), NewDecWithPrec(-100, 0), false, false, true}, + {NewDecWithPrec(-1, 1), NewDecWithPrec(-1, 1), false, false, true}, + {NewDecWithPrec(3333, 3), NewDecWithPrec(3333, 3), false, false, true}, + + {NewDecWithPrec(0, 0), NewDecWithPrec(3333, 3), false, true, false}, + {NewDecWithPrec(0, 0), NewDecWithPrec(100, 0), false, true, false}, + {NewDecWithPrec(-1, 0), NewDecWithPrec(3333, 3), false, true, false}, + {NewDecWithPrec(-1, 0), NewDecWithPrec(100, 0), false, true, false}, + {NewDecWithPrec(1111, 3), NewDecWithPrec(100, 0), false, true, false}, + {NewDecWithPrec(1111, 3), NewDecWithPrec(3333, 3), false, true, false}, + {NewDecWithPrec(-3333, 3), NewDecWithPrec(-1111, 3), false, true, false}, + + {NewDecWithPrec(3333, 3), NewDecWithPrec(0, 0), true, false, false}, + {NewDecWithPrec(100, 0), NewDecWithPrec(0, 0), true, false, false}, + {NewDecWithPrec(3333, 3), NewDecWithPrec(-1, 0), true, false, false}, + {NewDecWithPrec(100, 0), NewDecWithPrec(-1, 0), true, false, false}, + {NewDecWithPrec(100, 0), NewDecWithPrec(1111, 3), true, false, false}, + {NewDecWithPrec(3333, 3), NewDecWithPrec(1111, 3), true, false, false}, + {NewDecWithPrec(-1111, 3), NewDecWithPrec(-3333, 3), true, false, false}, + } + + for tcIndex, tc := range tests { + require.Equal(t, tc.gt, tc.d1.GT(tc.d2), "GT result is incorrect, tc %d", tcIndex) + require.Equal(t, tc.lt, tc.d1.LT(tc.d2), "LT result is incorrect, tc %d", tcIndex) + require.Equal(t, tc.eq, tc.d1.Equal(tc.d2), "equality result is incorrect, tc %d", tcIndex) + } + +} + +func TestDecsEqual(t *testing.T) { + tests := []struct { + d1s, d2s []Dec + eq bool + }{ + {[]Dec{NewDec(0)}, []Dec{NewDec(0)}, true}, + {[]Dec{NewDec(0)}, []Dec{NewDec(1)}, false}, + {[]Dec{NewDec(0)}, []Dec{}, false}, + {[]Dec{NewDec(0), NewDec(1)}, []Dec{NewDec(0), NewDec(1)}, true}, + {[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1), NewDec(0)}, true}, + {[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(0), NewDec(1)}, false}, + {[]Dec{NewDec(1), NewDec(0)}, []Dec{NewDec(1)}, false}, + {[]Dec{NewDec(1), NewDec(2)}, []Dec{NewDec(2), NewDec(4)}, false}, + {[]Dec{NewDec(3), NewDec(18)}, []Dec{NewDec(1), NewDec(6)}, false}, + } + + for tcIndex, tc := range tests { + require.Equal(t, tc.eq, DecsEqual(tc.d1s, tc.d2s), "equality of decional arrays is incorrect, tc %d", tcIndex) + require.Equal(t, tc.eq, DecsEqual(tc.d2s, tc.d1s), "equality of decional arrays is incorrect (converse), tc %d", tcIndex) + } +} + +func TestArithmetic(t *testing.T) { + tests := []struct { + d1, d2 Dec + expMul, expDiv, expAdd, expSub Dec + }{ + // d1 d2 MUL DIV ADD SUB + {NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0), NewDec(0)}, + {NewDec(1), NewDec(0), NewDec(0), NewDec(0), NewDec(1), NewDec(1)}, + {NewDec(0), NewDec(1), NewDec(0), NewDec(0), NewDec(1), NewDec(-1)}, + {NewDec(0), NewDec(-1), NewDec(0), NewDec(0), NewDec(-1), NewDec(1)}, + {NewDec(-1), NewDec(0), NewDec(0), NewDec(0), NewDec(-1), NewDec(-1)}, + + {NewDec(1), NewDec(1), NewDec(1), NewDec(1), NewDec(2), NewDec(0)}, + {NewDec(-1), NewDec(-1), NewDec(1), NewDec(1), NewDec(-2), NewDec(0)}, + {NewDec(1), NewDec(-1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(2)}, + {NewDec(-1), NewDec(1), NewDec(-1), NewDec(-1), NewDec(0), NewDec(-2)}, + + {NewDec(3), NewDec(7), NewDec(21), NewDecWithPrec(4285714286, 10), NewDec(10), NewDec(-4)}, + {NewDec(2), NewDec(4), NewDec(8), NewDecWithPrec(5, 1), NewDec(6), NewDec(-2)}, + {NewDec(100), NewDec(100), NewDec(10000), NewDec(1), NewDec(200), NewDec(0)}, + + {NewDecWithPrec(15, 1), NewDecWithPrec(15, 1), NewDecWithPrec(225, 2), + NewDec(1), NewDec(3), NewDec(0)}, + {NewDecWithPrec(3333, 4), NewDecWithPrec(333, 4), NewDecWithPrec(1109889, 8), + NewDecWithPrec(10009009009, 9), NewDecWithPrec(3666, 4), NewDecWithPrec(3, 1)}, + } + + for tcIndex, tc := range tests { + resAdd := tc.d1.Add(tc.d2) + resSub := tc.d1.Sub(tc.d2) + resMul := tc.d1.Mul(tc.d2) + require.True(t, tc.expAdd.Equal(resAdd), "exp %v, res %v, tc %d", tc.expAdd, resAdd, tcIndex) + require.True(t, tc.expSub.Equal(resSub), "exp %v, res %v, tc %d", tc.expSub, resSub, tcIndex) + require.True(t, tc.expMul.Equal(resMul), "exp %v, res %v, tc %d", tc.expMul, resMul, tcIndex) + + if tc.d2.IsZero() { // panic for divide by zero + require.Panics(t, func() { tc.d1.Quo(tc.d2) }) + } else { + resDiv := tc.d1.Quo(tc.d2) + require.True(t, tc.expDiv.Equal(resDiv), "exp %v, res %v, tc %d", tc.expDiv.String(), resDiv.String(), tcIndex) + } + } +} + +func TestBankerRoundChop(t *testing.T) { + tests := []struct { + d1 Dec + exp int64 + }{ + {mustNewDecFromStr(t, "0.25"), 0}, + {mustNewDecFromStr(t, "0"), 0}, + {mustNewDecFromStr(t, "1"), 1}, + {mustNewDecFromStr(t, "0.75"), 1}, + {mustNewDecFromStr(t, "0.5"), 0}, + {mustNewDecFromStr(t, "7.5"), 8}, + {mustNewDecFromStr(t, "1.5"), 2}, + {mustNewDecFromStr(t, "2.5"), 2}, + {mustNewDecFromStr(t, "0.545"), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even + {mustNewDecFromStr(t, "1.545"), 2}, + } + + for tcIndex, tc := range tests { + resNeg := tc.d1.Neg().RoundInt64() + require.Equal(t, -1*tc.exp, resNeg, "negative tc %d", tcIndex) + + resPos := tc.d1.RoundInt64() + require.Equal(t, tc.exp, resPos, "positive tc %d", tcIndex) + } +} + +func TestToLeftPadded(t *testing.T) { + tests := []struct { + dec Dec + digits int8 + exp string + }{ + {mustNewDecFromStr(t, "33.3"), 8, "00000033"}, + {mustNewDecFromStr(t, "50"), 8, "00000050"}, + {mustNewDecFromStr(t, "333"), 8, "00000333"}, + {mustNewDecFromStr(t, "333"), 12, "000000000333"}, + {mustNewDecFromStr(t, "0.3333"), 8, "00000000"}, + } + for tcIndex, tc := range tests { + res := tc.dec.ToLeftPadded(tc.digits) + require.Equal(t, tc.exp, res, "incorrect left padding, tc %d", tcIndex) + } +} + +var cdc = wire.NewCodec() + +func TestZeroDeserializationJSON(t *testing.T) { + d := Dec{new(big.Int)} + err := cdc.UnmarshalJSON([]byte(`"0"`), &d) + require.Nil(t, err) + err = cdc.UnmarshalJSON([]byte(`"{}"`), &d) + require.NotNil(t, err) +} + +func TestSerializationText(t *testing.T) { + d := mustNewDecFromStr(t, "0.333") + + bz, err := d.MarshalText() + require.NoError(t, err) + + d2 := Dec{new(big.Int)} + err = d2.UnmarshalText(bz) + require.NoError(t, err) + require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2) +} + +func TestSerializationGoWireJSON(t *testing.T) { + d := mustNewDecFromStr(t, "0.333") + + bz, err := cdc.MarshalJSON(d) + require.NoError(t, err) + + d2 := Dec{new(big.Int)} + err = cdc.UnmarshalJSON(bz, &d2) + require.NoError(t, err) + require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2) +} + +func TestSerializationGoWireBinary(t *testing.T) { + d := mustNewDecFromStr(t, "0.333") + + bz, err := cdc.MarshalBinary(d) + require.NoError(t, err) + + var d2 Dec + err = cdc.UnmarshalBinary(bz, &d2) + require.NoError(t, err) + require.True(t, d.Equal(d2), "original: %v, unmarshalled: %v", d, d2) +} + +type testDEmbedStruct struct { + Field1 string `json:"f1"` + Field2 int `json:"f2"` + Field3 Dec `json:"f3"` +} + +// TODO make work for UnmarshalJSON +func TestEmbeddedStructSerializationGoWire(t *testing.T) { + obj := testDEmbedStruct{"foo", 10, NewDecWithPrec(1, 3)} + bz, err := cdc.MarshalBinary(obj) + require.Nil(t, err) + + var obj2 testDEmbedStruct + err = cdc.UnmarshalBinary(bz, &obj2) + require.Nil(t, err) + + require.Equal(t, obj.Field1, obj2.Field1) + require.Equal(t, obj.Field2, obj2.Field2) + require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2) +} + +func TestStringOverflow(t *testing.T) { + // two random 64 bit primes + dec1, err := NewDecFromStr("51643150036226787134389711697696177267") + require.NoError(t, err) + dec2, err := NewDecFromStr("-31798496660535729618459429845579852627") + require.NoError(t, err) + dec3 := dec1.Add(dec2) + require.Equal(t, + "19844653375691057515930281852116324640.0000000000", + dec3.String(), + ) +} diff --git a/types/rational.go b/types/rational.go deleted file mode 100644 index 89cc76968..000000000 --- a/types/rational.go +++ /dev/null @@ -1,262 +0,0 @@ -package types - -import ( - "fmt" - "math/big" - "strconv" - "strings" - "testing" -) - -// "that's one big rat!" -// ______ -// / / /\ \____oo -// __ /___...._____ _\o -// __| |_ |_ - -// NOTE: never use new(Rat) or else -// we will panic unmarshalling into the -// nil embedded big.Rat -type Rat struct { - *big.Rat `json:"rat"` -} - -// nolint - common values -func ZeroRat() Rat { return Rat{big.NewRat(0, 1)} } -func OneRat() Rat { return Rat{big.NewRat(1, 1)} } - -// New - create a new Rat from integers -func NewRat(Numerator int64, Denominator ...int64) Rat { - switch len(Denominator) { - case 0: - return Rat{big.NewRat(Numerator, 1)} - case 1: - return Rat{big.NewRat(Numerator, Denominator[0])} - default: - panic("improper use of New, can only have one denominator") - } -} - -func getNumeratorDenominator(str []string, prec int) (numerator string, denom int64, err Error) { - switch len(str) { - case 1: - if len(str[0]) == 0 { - return "", 0, ErrUnknownRequest("not a decimal string") - } - numerator = str[0] - return numerator, 1, nil - case 2: - if len(str[0]) == 0 || len(str[1]) == 0 { - return "", 0, ErrUnknownRequest("not a decimal string") - } - if len(str[1]) > prec { - return "", 0, ErrUnknownRequest("string has too many decimals") - } - numerator = str[0] + str[1] - len := int64(len(str[1])) - denom = new(big.Int).Exp(big.NewInt(10), big.NewInt(len), nil).Int64() - return numerator, denom, nil - default: - return "", 0, ErrUnknownRequest("not a decimal string") - } -} - -// create a rational from decimal string or integer string -// precision is the number of values after the decimal point which should be read -func NewRatFromDecimal(decimalStr string, prec int) (f Rat, err Error) { - // first extract any negative symbol - if len(decimalStr) == 0 { - return f, ErrUnknownRequest("decimal string is empty") - } - - neg := false - if string(decimalStr[0]) == "-" { - neg = true - decimalStr = decimalStr[1:] - } - - str := strings.Split(decimalStr, ".") - - numStr, denom, err := getNumeratorDenominator(str, prec) - if err != nil { - return f, err - } - - num, errConv := strconv.Atoi(numStr) - if errConv != nil && strings.HasSuffix(errConv.Error(), "value out of range") { - // resort to big int, don't make this default option for efficiency - numBig, success := new(big.Int).SetString(numStr, 10) - if success != true { - return f, ErrUnknownRequest("not a decimal string") - } - - if neg { - numBig.Neg(numBig) - } - - return NewRatFromBigInt(numBig, big.NewInt(denom)), nil - } else if errConv != nil { - return f, ErrUnknownRequest("not a decimal string") - } - - if neg { - num *= -1 - } - - return NewRat(int64(num), denom), nil -} - -// NewRatFromBigInt constructs Rat from big.Int -func NewRatFromBigInt(num *big.Int, denom ...*big.Int) Rat { - switch len(denom) { - case 0: - return Rat{new(big.Rat).SetInt(num)} - case 1: - return Rat{new(big.Rat).SetFrac(num, denom[0])} - default: - panic("improper use of NewRatFromBigInt, can only have one denominator") - } -} - -// NewRatFromInt constructs Rat from Int -func NewRatFromInt(num Int, denom ...Int) Rat { - switch len(denom) { - case 0: - return Rat{new(big.Rat).SetInt(num.BigInt())} - case 1: - return Rat{new(big.Rat).SetFrac(num.BigInt(), denom[0].BigInt())} - default: - panic("improper use of NewRatFromBigInt, can only have one denominator") - } -} - -//nolint -func (r Rat) Num() Int { return Int{r.Rat.Num()} } // Num - return the numerator -func (r Rat) Denom() Int { return Int{r.Rat.Denom()} } // Denom - return the denominator -func (r Rat) IsZero() bool { return r.Num().IsZero() } // IsZero - Is the Rat equal to zero -func (r Rat) Equal(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 0 } -func (r Rat) GT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == 1 } // greater than -func (r Rat) GTE(r2 Rat) bool { return !r.LT(r2) } // greater than or equal -func (r Rat) LT(r2 Rat) bool { return (r.Rat).Cmp(r2.Rat) == -1 } // less than -func (r Rat) LTE(r2 Rat) bool { return !r.GT(r2) } // less than or equal -func (r Rat) Mul(r2 Rat) Rat { return Rat{new(big.Rat).Mul(r.Rat, r2.Rat)} } // Mul - multiplication -func (r Rat) Quo(r2 Rat) Rat { return Rat{new(big.Rat).Quo(r.Rat, r2.Rat)} } // Quo - quotient -func (r Rat) Add(r2 Rat) Rat { return Rat{new(big.Rat).Add(r.Rat, r2.Rat)} } // Add - addition -func (r Rat) Sub(r2 Rat) Rat { return Rat{new(big.Rat).Sub(r.Rat, r2.Rat)} } // Sub - subtraction -func (r Rat) String() string { return r.Rat.String() } -func (r Rat) FloatString() string { return r.Rat.FloatString(10) } // a human-friendly string format. The last digit is rounded to nearest, with halves rounded away from zero. - -var ( - zero = big.NewInt(0) - one = big.NewInt(1) - two = big.NewInt(2) - five = big.NewInt(5) - nFive = big.NewInt(-5) - ten = big.NewInt(10) -) - -// evaluate the rational using bankers rounding -func (r Rat) EvaluateBig() *big.Int { - - num := r.Rat.Num() - denom := r.Rat.Denom() - - d, rem := new(big.Int), new(big.Int) - d.QuoRem(num, denom, rem) - if rem.Cmp(zero) == 0 { // is the remainder zero - return d - } - - // evaluate the remainder using bankers rounding - tenNum := new(big.Int).Mul(num, ten) - tenD := new(big.Int).Mul(d, ten) - remainderDigit := new(big.Int).Sub(new(big.Int).Quo(tenNum, denom), tenD) // get the first remainder digit - isFinalDigit := (new(big.Int).Rem(tenNum, denom).Cmp(zero) == 0) // is this the final digit in the remainder? - - switch { - case isFinalDigit && (remainderDigit.Cmp(five) == 0 || remainderDigit.Cmp(nFive) == 0): - dRem2 := new(big.Int).Rem(d, two) - return new(big.Int).Add(d, dRem2) // always rounds to the even number - case remainderDigit.Cmp(five) != -1: //remainderDigit >= 5: - d.Add(d, one) - case remainderDigit.Cmp(nFive) != 1: //remainderDigit <= -5: - d.Sub(d, one) - } - return d -} - -// RoundInt64 rounds the rational using bankers rounding -func (r Rat) RoundInt64() int64 { - return r.EvaluateBig().Int64() -} - -// RoundInt round the rational using bankers rounding -func (r Rat) RoundInt() Int { - return NewIntFromBigInt(r.EvaluateBig()) -} - -// round Rat with the provided precisionFactor -func (r Rat) Round(precisionFactor int64) Rat { - rTen := Rat{new(big.Rat).Mul(r.Rat, big.NewRat(precisionFactor, 1))} - return Rat{big.NewRat(rTen.RoundInt64(), precisionFactor)} -} - -// TODO panic if negative or if totalDigits < len(initStr)??? -// evaluate as an integer and return left padded string -func (r Rat) ToLeftPadded(totalDigits int8) string { - intStr := r.EvaluateBig().String() - fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s` - return fmt.Sprintf(fcode, intStr) -} - -//___________________________________________________________________________________ - -//Wraps r.MarshalText(). -func (r Rat) MarshalAmino() (string, error) { - if r.Rat == nil { - r.Rat = new(big.Rat) - } - bz, err := r.Rat.MarshalText() - return string(bz), err -} - -// Requires a valid JSON string - strings quotes and calls UnmarshalText -func (r *Rat) UnmarshalAmino(text string) (err error) { - tempRat := big.NewRat(0, 1) - err = tempRat.UnmarshalText([]byte(text)) - if err != nil { - return err - } - r.Rat = tempRat - return nil -} - -//___________________________________________________________________________________ -// helpers - -// test if two rat arrays are equal -func RatsEqual(r1s, r2s []Rat) bool { - if len(r1s) != len(r2s) { - return false - } - - for i, r1 := range r1s { - if !r1.Equal(r2s[i]) { - return false - } - } - return true -} - -// intended to be used with require/assert: require.True(RatEq(...)) -func RatEq(t *testing.T, exp, got Rat) (*testing.T, bool, string, Rat, Rat) { - return t, exp.Equal(got), "expected:\t%v\ngot:\t\t%v", exp, got -} - -// minimum rational between two -func MinRat(r1, r2 Rat) Rat { - if r1.LT(r2) { - return r1 - } - return r2 -} diff --git a/types/rational_test.go b/types/rational_test.go deleted file mode 100644 index 940de23dc..000000000 --- a/types/rational_test.go +++ /dev/null @@ -1,402 +0,0 @@ -package types - -import ( - "math/big" - "math/rand" - "testing" - - wire "github.com/cosmos/cosmos-sdk/wire" - "github.com/stretchr/testify/require" -) - -func TestNew(t *testing.T) { - require.Equal(t, NewRat(1), NewRat(1, 1)) - require.Equal(t, NewRat(100), NewRat(100, 1)) - require.Equal(t, NewRat(-1), NewRat(-1, 1)) - require.Equal(t, NewRat(-100), NewRat(-100, 1)) - require.Equal(t, NewRat(0), NewRat(0, 1)) - - // do not allow for more than 2 variables - require.Panics(t, func() { NewRat(1, 1, 1) }) -} - -func TestNewFromDecimal(t *testing.T) { - largeBigInt, success := new(big.Int).SetString("3109736052979742687701388262607869", 10) - require.True(t, success) - tests := []struct { - decimalStr string - expErr bool - exp Rat - }{ - {"", true, Rat{}}, - {"0", false, NewRat(0)}, - {"1", false, NewRat(1)}, - {"1.1", false, NewRat(11, 10)}, - {"0.75", false, NewRat(3, 4)}, - {"0.8", false, NewRat(4, 5)}, - {"0.11111", true, NewRat(1111, 10000)}, - {"628240629832763.5738930323617075341", true, NewRat(3141203149163817869, 5000)}, - {"621947210595948537540277652521.5738930323617075341", - true, NewRatFromBigInt(largeBigInt, big.NewInt(5000))}, - {"628240629832763.5738", false, NewRat(3141203149163817869, 5000)}, - {"621947210595948537540277652521.5738", - false, NewRatFromBigInt(largeBigInt, big.NewInt(5000))}, - {".", true, Rat{}}, - {".0", true, Rat{}}, - {"1.", true, Rat{}}, - {"foobar", true, Rat{}}, - {"0.foobar", true, Rat{}}, - {"0.foobar.", true, Rat{}}, - } - - for tcIndex, tc := range tests { - res, err := NewRatFromDecimal(tc.decimalStr, 4) - if tc.expErr { - require.NotNil(t, err, tc.decimalStr, "error expected, tc #%d", tcIndex) - } else { - require.Nil(t, err, tc.decimalStr, "unexpected error, tc #%d", tcIndex) - require.True(t, res.Equal(tc.exp), tc.decimalStr, "equality was incorrect, tc #%d", tcIndex) - } - - // negative tc - res, err = NewRatFromDecimal("-"+tc.decimalStr, 4) - if tc.expErr { - require.NotNil(t, err, tc.decimalStr, "error expected (negative case), tc #%d", tcIndex) - } else { - require.Nil(t, err, tc.decimalStr, "unexpected error (negative case), tc #%d", tcIndex) - require.True(t, res.Equal(tc.exp.Mul(NewRat(-1))), tc.decimalStr, "equality was incorrect (negative case), tc #%d", tcIndex) - } - } -} - -func TestEqualities(t *testing.T) { - tests := []struct { - r1, r2 Rat - gt, lt, eq bool - }{ - {NewRat(0), NewRat(0), false, false, true}, - {NewRat(0, 100), NewRat(0, 10000), false, false, true}, - {NewRat(100), NewRat(100), false, false, true}, - {NewRat(-100), NewRat(-100), false, false, true}, - {NewRat(-100, -1), NewRat(100), false, false, true}, - {NewRat(-1, 1), NewRat(1, -1), false, false, true}, - {NewRat(1, -1), NewRat(-1, 1), false, false, true}, - {NewRat(3, 7), NewRat(3, 7), false, false, true}, - - {NewRat(0), NewRat(3, 7), false, true, false}, - {NewRat(0), NewRat(100), false, true, false}, - {NewRat(-1), NewRat(3, 7), false, true, false}, - {NewRat(-1), NewRat(100), false, true, false}, - {NewRat(1, 7), NewRat(100), false, true, false}, - {NewRat(1, 7), NewRat(3, 7), false, true, false}, - {NewRat(-3, 7), NewRat(-1, 7), false, true, false}, - - {NewRat(3, 7), NewRat(0), true, false, false}, - {NewRat(100), NewRat(0), true, false, false}, - {NewRat(3, 7), NewRat(-1), true, false, false}, - {NewRat(100), NewRat(-1), true, false, false}, - {NewRat(100), NewRat(1, 7), true, false, false}, - {NewRat(3, 7), NewRat(1, 7), true, false, false}, - {NewRat(-1, 7), NewRat(-3, 7), true, false, false}, - } - - for tcIndex, tc := range tests { - require.Equal(t, tc.gt, tc.r1.GT(tc.r2), "GT result is incorrect, tc #%d", tcIndex) - require.Equal(t, tc.lt, tc.r1.LT(tc.r2), "LT result is incorrect, tc #%d", tcIndex) - require.Equal(t, tc.eq, tc.r1.Equal(tc.r2), "equality result is incorrect, tc #%d", tcIndex) - } - -} - -func TestArithmetic(t *testing.T) { - tests := []struct { - r1, r2 Rat - resMul, resDiv, resAdd, resSub Rat - }{ - // r1 r2 MUL DIV ADD SUB - {NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0), NewRat(0)}, - {NewRat(1), NewRat(0), NewRat(0), NewRat(0), NewRat(1), NewRat(1)}, - {NewRat(0), NewRat(1), NewRat(0), NewRat(0), NewRat(1), NewRat(-1)}, - {NewRat(0), NewRat(-1), NewRat(0), NewRat(0), NewRat(-1), NewRat(1)}, - {NewRat(-1), NewRat(0), NewRat(0), NewRat(0), NewRat(-1), NewRat(-1)}, - - {NewRat(1), NewRat(1), NewRat(1), NewRat(1), NewRat(2), NewRat(0)}, - {NewRat(-1), NewRat(-1), NewRat(1), NewRat(1), NewRat(-2), NewRat(0)}, - {NewRat(1), NewRat(-1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(2)}, - {NewRat(-1), NewRat(1), NewRat(-1), NewRat(-1), NewRat(0), NewRat(-2)}, - - {NewRat(3), NewRat(7), NewRat(21), NewRat(3, 7), NewRat(10), NewRat(-4)}, - {NewRat(2), NewRat(4), NewRat(8), NewRat(1, 2), NewRat(6), NewRat(-2)}, - {NewRat(100), NewRat(100), NewRat(10000), NewRat(1), NewRat(200), NewRat(0)}, - - {NewRat(3, 2), NewRat(3, 2), NewRat(9, 4), NewRat(1), NewRat(3), NewRat(0)}, - {NewRat(3, 7), NewRat(7, 3), NewRat(1), NewRat(9, 49), NewRat(58, 21), NewRat(-40, 21)}, - {NewRat(1, 21), NewRat(11, 5), NewRat(11, 105), NewRat(5, 231), NewRat(236, 105), NewRat(-226, 105)}, - {NewRat(-21), NewRat(3, 7), NewRat(-9), NewRat(-49), NewRat(-144, 7), NewRat(-150, 7)}, - {NewRat(100), NewRat(1, 7), NewRat(100, 7), NewRat(700), NewRat(701, 7), NewRat(699, 7)}, - } - - for tcIndex, tc := range tests { - require.True(t, tc.resMul.Equal(tc.r1.Mul(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex) - require.True(t, tc.resAdd.Equal(tc.r1.Add(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex) - require.True(t, tc.resSub.Equal(tc.r1.Sub(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex) - - if tc.r2.Num().IsZero() { // panic for divide by zero - require.Panics(t, func() { tc.r1.Quo(tc.r2) }) - } else { - require.True(t, tc.resDiv.Equal(tc.r1.Quo(tc.r2)), "r1 %v, r2 %v. tc #%d", tc.r1.Rat, tc.r2.Rat, tcIndex) - } - } -} - -func TestEvaluate(t *testing.T) { - tests := []struct { - r1 Rat - res int64 - }{ - {NewRat(0), 0}, - {NewRat(1), 1}, - {NewRat(1, 4), 0}, - {NewRat(1, 2), 0}, - {NewRat(3, 4), 1}, - {NewRat(5, 6), 1}, - {NewRat(3, 2), 2}, - {NewRat(5, 2), 2}, - {NewRat(6, 11), 1}, // 0.545-> 1 even though 5 is first decimal and 1 not even - {NewRat(17, 11), 2}, // 1.545 - {NewRat(5, 11), 0}, - {NewRat(16, 11), 1}, - {NewRat(113, 12), 9}, - } - - for tcIndex, tc := range tests { - require.Equal(t, tc.res, tc.r1.RoundInt64(), "%v. tc #%d", tc.r1, tcIndex) - require.Equal(t, tc.res*-1, tc.r1.Mul(NewRat(-1)).RoundInt64(), "%v. tc #%d", tc.r1.Mul(NewRat(-1)), tcIndex) - } -} - -func TestRound(t *testing.T) { - many3 := "333333333333333333333333333333333333333333333" - many7 := "777777777777777777777777777777777777777777777" - big3, worked := new(big.Int).SetString(many3, 10) - require.True(t, worked) - big7, worked := new(big.Int).SetString(many7, 10) - require.True(t, worked) - - tests := []struct { - r, res Rat - precFactor int64 - }{ - {NewRat(333, 777), NewRat(429, 1000), 1000}, - {Rat{new(big.Rat).SetFrac(big3, big7)}, NewRat(429, 1000), 1000}, - {Rat{new(big.Rat).SetFrac(big3, big7)}, Rat{big.NewRat(4285714286, 10000000000)}, 10000000000}, - {NewRat(1, 2), NewRat(1, 2), 1000}, - } - - for tcIndex, tc := range tests { - require.Equal(t, tc.res, tc.r.Round(tc.precFactor), "%v", tc.r, "incorrect rounding, tc #%d", tcIndex) - negR1, negRes := tc.r.Mul(NewRat(-1)), tc.res.Mul(NewRat(-1)) - require.Equal(t, negRes, negR1.Round(tc.precFactor), "%v", negR1, "incorrect rounding (negative case), tc #%d", tcIndex) - } -} - -func TestToLeftPadded(t *testing.T) { - tests := []struct { - rat Rat - digits int8 - res string - }{ - {NewRat(100, 3), 8, "00000033"}, - {NewRat(1, 3), 8, "00000000"}, - {NewRat(100, 2), 8, "00000050"}, - {NewRat(1000, 3), 8, "00000333"}, - {NewRat(1000, 3), 12, "000000000333"}, - } - for tcIndex, tc := range tests { - require.Equal(t, tc.res, tc.rat.ToLeftPadded(tc.digits), "incorrect left padding, tc #%d", tcIndex) - } -} - -var cdc = wire.NewCodec() //var jsonCdc JSONCodec // TODO wire.Codec - -func TestZeroSerializationJSON(t *testing.T) { - r := NewRat(0, 1) - err := cdc.UnmarshalJSON([]byte(`"0/1"`), &r) - require.Nil(t, err) - err = cdc.UnmarshalJSON([]byte(`"0/0"`), &r) - require.NotNil(t, err) - err = cdc.UnmarshalJSON([]byte(`"1/0"`), &r) - require.NotNil(t, err) - err = cdc.UnmarshalJSON([]byte(`"{}"`), &r) - require.NotNil(t, err) -} - -func TestSerializationText(t *testing.T) { - r := NewRat(1, 3) - - bz, err := r.MarshalText() - require.NoError(t, err) - - var r2 = Rat{new(big.Rat)} - err = r2.UnmarshalText(bz) - require.NoError(t, err) - require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2) -} - -func TestSerializationGoWireJSON(t *testing.T) { - r := NewRat(1, 3) - bz, err := cdc.MarshalJSON(r) - require.NoError(t, err) - - var r2 Rat - err = cdc.UnmarshalJSON(bz, &r2) - require.NoError(t, err) - require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2) -} - -func TestSerializationGoWireBinary(t *testing.T) { - r := NewRat(1, 3) - bz, err := cdc.MarshalBinary(r) - require.NoError(t, err) - - var r2 Rat - err = cdc.UnmarshalBinary(bz, &r2) - require.NoError(t, err) - require.True(t, r.Equal(r2), "original: %v, unmarshalled: %v", r, r2) -} - -type testEmbedStruct struct { - Field1 string `json:"f1"` - Field2 int `json:"f2"` - Field3 Rat `json:"f3"` -} - -func TestEmbeddedStructSerializationGoWire(t *testing.T) { - obj := testEmbedStruct{"foo", 10, NewRat(1, 3)} - bz, err := cdc.MarshalJSON(obj) - require.Nil(t, err) - - var obj2 testEmbedStruct - err = cdc.UnmarshalJSON(bz, &obj2) - require.Nil(t, err) - - require.Equal(t, obj.Field1, obj2.Field1) - require.Equal(t, obj.Field2, obj2.Field2) - require.True(t, obj.Field3.Equal(obj2.Field3), "original: %v, unmarshalled: %v", obj, obj2) -} - -func TestRatsEqual(t *testing.T) { - tests := []struct { - r1s, r2s []Rat - eq bool - }{ - {[]Rat{NewRat(0)}, []Rat{NewRat(0)}, true}, - {[]Rat{NewRat(0)}, []Rat{NewRat(1)}, false}, - {[]Rat{NewRat(0)}, []Rat{}, false}, - {[]Rat{NewRat(0), NewRat(1)}, []Rat{NewRat(0), NewRat(1)}, true}, - {[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1), NewRat(0)}, true}, - {[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(0), NewRat(1)}, false}, - {[]Rat{NewRat(1), NewRat(0)}, []Rat{NewRat(1)}, false}, - {[]Rat{NewRat(1), NewRat(2)}, []Rat{NewRat(2), NewRat(4)}, false}, - {[]Rat{NewRat(3), NewRat(18)}, []Rat{NewRat(1), NewRat(6)}, false}, - } - - for tcIndex, tc := range tests { - require.Equal(t, tc.eq, RatsEqual(tc.r1s, tc.r2s), "equality of rational arrays is incorrect, tc #%d", tcIndex) - require.Equal(t, tc.eq, RatsEqual(tc.r2s, tc.r1s), "equality of rational arrays is incorrect (converse), tc #%d", tcIndex) - } - -} - -func TestStringOverflow(t *testing.T) { - // two random 64 bit primes - rat1 := NewRat(5164315003622678713, 4389711697696177267) - rat2 := NewRat(-3179849666053572961, 8459429845579852627) - rat3 := rat1.Add(rat2) - require.Equal(t, - "29728537197630860939575850336935951464/37134458148982045574552091851127630409", - rat3.String(), - ) -} - -// Tests below uses randomness -// Since we are using *big.Rat as underlying value -// and (U/)Int is immutable value(see TestImmutability(U/)Int) -// it is safe to use randomness in the tests -func TestArithRat(t *testing.T) { - for i := 0; i < 20; i++ { - n1 := NewInt(int64(rand.Int31())) - d1 := NewInt(int64(rand.Int31())) - rat1 := NewRatFromInt(n1, d1) - - n2 := NewInt(int64(rand.Int31())) - d2 := NewInt(int64(rand.Int31())) - rat2 := NewRatFromInt(n2, d2) - - n1d2 := n1.Mul(d2) - n2d1 := n2.Mul(d1) - - cases := []struct { - nres Int - dres Int - rres Rat - }{ - {n1d2.Add(n2d1), d1.Mul(d2), rat1.Add(rat2)}, - {n1d2.Sub(n2d1), d1.Mul(d2), rat1.Sub(rat2)}, - {n1.Mul(n2), d1.Mul(d2), rat1.Mul(rat2)}, - {n1d2, n2d1, rat1.Quo(rat2)}, - } - - for _, tc := range cases { - require.Equal(t, NewRatFromInt(tc.nres, tc.dres), tc.rres) - } - } -} - -func TestCompRat(t *testing.T) { - for i := 0; i < 20; i++ { - n1 := NewInt(int64(rand.Int31())) - d1 := NewInt(int64(rand.Int31())) - rat1 := NewRatFromInt(n1, d1) - - n2 := NewInt(int64(rand.Int31())) - d2 := NewInt(int64(rand.Int31())) - rat2 := NewRatFromInt(n2, d2) - - n1d2 := n1.Mul(d2) - n2d1 := n2.Mul(d1) - - cases := []struct { - ires bool - rres bool - }{ - {n1d2.Equal(n2d1), rat1.Equal(rat2)}, - {n1d2.GT(n2d1), rat1.GT(rat2)}, - {n1d2.LT(n2d1), rat1.LT(rat2)}, - {n1d2.GT(n2d1) || n1d2.Equal(n2d1), rat1.GTE(rat2)}, - {n1d2.LT(n2d1) || n1d2.Equal(n2d1), rat1.LTE(rat2)}, - } - - for _, tc := range cases { - require.Equal(t, tc.ires, tc.rres) - } - } -} - -func TestImmutabilityRat(t *testing.T) { - for i := 0; i < 20; i++ { - n := int64(rand.Int31()) - r := NewRat(n) - z := ZeroRat() - o := OneRat() - - r.Add(z) - r.Sub(z) - r.Mul(o) - r.Quo(o) - - require.Equal(t, n, r.RoundInt64()) - require.True(t, NewRat(n).Equal(r)) - } - -} diff --git a/types/stake.go b/types/stake.go index 4e3cf38a3..acd24a154 100644 --- a/types/stake.go +++ b/types/stake.go @@ -42,9 +42,9 @@ type Validator interface { GetStatus() BondStatus // status of the validator GetOwner() AccAddress // owner AccAddress to receive/return validators coins GetPubKey() crypto.PubKey // validation pubkey - GetPower() Rat // validation power - GetTokens() Rat // validation tokens - GetDelegatorShares() Rat // Total out standing delegator shares + GetPower() Dec // validation power + GetTokens() Dec // validation tokens + GetDelegatorShares() Dec // Total out standing delegator shares GetBondHeight() int64 // height in which the validator became active } @@ -68,10 +68,10 @@ type ValidatorSet interface { Validator(Context, AccAddress) Validator // get a particular validator by owner AccAddress ValidatorByPubKey(Context, crypto.PubKey) Validator // get a particular validator by signing PubKey - TotalPower(Context) Rat // total power of the validator set + TotalPower(Context) Dec // total power of the validator set // slash the validator and delegators of the validator, specifying offence height, offence power, and slash fraction - Slash(Context, crypto.PubKey, int64, int64, Rat) + Slash(Context, crypto.PubKey, int64, int64, Dec) Revoke(Context, crypto.PubKey) // revoke a validator Unrevoke(Context, crypto.PubKey) // unrevoke a validator } @@ -82,7 +82,7 @@ type ValidatorSet interface { type Delegation interface { GetDelegator() AccAddress // delegator AccAddress for the bond GetValidator() AccAddress // validator owner AccAddress for the bond - GetBondShares() Rat // amount of validator's shares + GetBondShares() Dec // amount of validator's shares } // properties for the set of all delegations for a particular diff --git a/x/distribution/keeper.go b/x/distribution/keeper.go index 145071719..aba07eaca 100644 --- a/x/distribution/keeper.go +++ b/x/distribution/keeper.go @@ -23,13 +23,13 @@ package stake ////_________________________________________________________________________ //// cummulative power of the non-absent prevotes -//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Rat { +//func (k Keeper) GetTotalPrecommitVotingPower(ctx sdk.Context) sdk.Dec { //store := ctx.KVStore(k.storeKey) //// get absent prevote indexes //absents := ctx.AbsentValidators() -//TotalPower := sdk.ZeroRat() +//TotalPower := sdk.ZeroDec() //i := int32(0) //iterator := store.SubspaceIterator(ValidatorsBondedKey) //for ; iterator.Valid(); iterator.Next() { diff --git a/x/distribution/keeper_test.go b/x/distribution/keeper_test.go index 0d732f8a1..890268060 100644 --- a/x/distribution/keeper_test.go +++ b/x/distribution/keeper_test.go @@ -8,8 +8,8 @@ package stake //var candidatesIn [5]Candidate //for i, amt := range amts { //candidatesIn[i] = NewCandidate(addrVals[i], pks[i], Description{}) -//candidatesIn[i].BondedShares = sdk.NewRat(amt) -//candidatesIn[i].DelegatorShares = sdk.NewRat(amt) +//candidatesIn[i].BondedShares = sdk.NewDec(amt) +//candidatesIn[i].DelegatorShares = sdk.NewDec(amt) //keeper.setCandidate(ctx, candidatesIn[i]) //} @@ -18,7 +18,7 @@ package stake //require.Equal(t, 5, len(gotValidators)) //totPow := keeper.GetTotalPrecommitVotingPower(ctx) -//exp := sdk.NewRat(11111) +//exp := sdk.NewDec(11111) //require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) //// set absent gotValidators to be the 1st and 3rd record sorted by pubKey address @@ -26,6 +26,6 @@ package stake //totPow = keeper.GetTotalPrecommitVotingPower(ctx) //// XXX verify that this order should infact exclude these two records -//exp = sdk.NewRat(11100) +//exp = sdk.NewDec(11100) //require.True(t, exp.Equal(totPow), "exp %v, got %v", exp, totPow) //} diff --git a/x/distribution/movement.go b/x/distribution/movement.go index 03c4de72c..399a25a68 100644 --- a/x/distribution/movement.go +++ b/x/distribution/movement.go @@ -17,7 +17,7 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} //// calculate the proposer reward //precommitPower := k.GetTotalPrecommitVotingPower(ctx) -//toProposer := coinsMulRat(collectedFees, (sdk.NewRat(1, 100).Add(sdk.NewRat(4, 100).Mul(precommitPower).Quo(pool.BondedShares)))) +//toProposer := coinsMulRat(collectedFees, (sdk.NewDec(1, 100).Add(sdk.NewDec(4, 100).Mul(precommitPower).Quo(pool.BondedShares)))) //candidate.ProposerRewardPool = candidate.ProposerRewardPool.Plus(toProposer) //toReservePool := coinsMulRat(collectedFees, params.ReservePoolFee) @@ -34,10 +34,10 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} //k.setPool(ctx, pool) //} -//func coinsMulRat(coins sdk.Coins, rat sdk.Rat) sdk.Coins { +//func coinsMulRat(coins sdk.Coins, rat sdk.Dec) sdk.Coins { //var res sdk.Coins //for _, coin := range coins { -//coinMulAmt := rat.Mul(sdk.NewRat(coin.Amount)).Evaluate() +//coinMulAmt := rat.Mul(sdk.NewDec(coin.Amount)).Evaluate() //coinMul := sdk.Coins{{coin.Denom, coinMulAmt}} //res = res.Plus(coinMul) //} @@ -49,14 +49,14 @@ func BurnFeeHandler(ctx sdk.Context, _ sdk.Tx, collectedFees sdk.Coins) {} //// calculate adjustment changes for a candidate at a height //func CalculateAdjustmentChange(candidate Candidate, pool Pool, denoms []string, height int64) (Candidate, Pool) { -//heightRat := sdk.NewRat(height) -//lastHeightRat := sdk.NewRat(height - 1) +//heightRat := sdk.NewDec(height) +//lastHeightRat := sdk.NewDec(height - 1) //candidateFeeCount := candidate.BondedShares.Mul(heightRat) //poolFeeCount := pool.BondedShares.Mul(heightRat) //for i, denom := range denoms { -//poolFeeSumReceived := sdk.NewRat(pool.FeeSumReceived.AmountOf(denom)) -//poolFeeRecent := sdk.NewRat(pool.FeeRecent.AmountOf(denom)) +//poolFeeSumReceived := sdk.NewDec(pool.FeeSumReceived.AmountOf(denom)) +//poolFeeRecent := sdk.NewDec(pool.FeeRecent.AmountOf(denom)) //// calculate simple and projected pools //simplePool := candidateFeeCount.Quo(poolFeeCount).Mul(poolFeeSumReceived) //calc1 := candidate.PrevBondedShares.Mul(lastHeightRat).Quo(pool.PrevBondedShares.Mul(lastHeightRat)).Mul(poolFeeRecent) diff --git a/x/distribution/types.go b/x/distribution/types.go index f9d4f905f..223410471 100644 --- a/x/distribution/types.go +++ b/x/distribution/types.go @@ -23,8 +23,8 @@ package stake //// fee information for a validator //type Validator struct { -//Adjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools +//Adjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms +//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // total shares of a global hold pools //} ////_________________________________________________________________________ @@ -32,7 +32,7 @@ package stake //// Params defines the high level settings for staking //type Params struct { //FeeDenoms []string `json:"fee_denoms"` // accepted fee denoms -//ReservePoolFee sdk.Rat `json:"reserve_pool_fee"` // percent of fees which go to reserve pool +//ReservePoolFee sdk.Dec `json:"reserve_pool_fee"` // percent of fees which go to reserve pool //} //func (p Params) equal(p2 Params) bool { @@ -43,7 +43,7 @@ package stake //func defaultParams() Params { //return Params{ //FeeDenoms: []string{"steak"}, -//ReservePoolFee: sdk.NewRat(5, 100), +//ReservePoolFee: sdk.NewDec(5, 100), //} //} @@ -55,8 +55,8 @@ package stake //FeePool sdk.Coins `json:"fee_pool"` // XXX fee pool for all the fee shares which have already been distributed //FeeSumReceived sdk.Coins `json:"fee_sum_received"` // XXX sum of all fees received, post reserve pool `json:"fee_sum_received"` //FeeRecent sdk.Coins `json:"fee_recent"` // XXX most recent fee collected -//FeeAdjustments []sdk.Rat `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms -//PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // XXX last recorded bonded shares +//FeeAdjustments []sdk.Dec `json:"fee_adjustments"` // XXX Adjustment factors for lazy fee accounting, couples with Params.BondDenoms +//PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // XXX last recorded bonded shares //} //func (p Pool) equal(p2 Pool) bool { @@ -64,7 +64,7 @@ package stake //p.FeePool.IsEqual(p2.FeePool) && //p.FeeSumReceived.IsEqual(p2.FeeSumReceived) && //p.FeeRecent.IsEqual(p2.FeeRecent) && -//sdk.RatsEqual(p.FeeAdjustments, p2.FeeAdjustments) && +//sdk.DecsEqual(p.FeeAdjustments, p2.FeeAdjustments) && //p.PrevBondedShares.Equal(p2.PrevBondedShares) //} @@ -75,8 +75,8 @@ package stake //FeePool: sdk.Coins(nil), //FeeSumReceived: sdk.Coins(nil), //FeeRecent: sdk.Coins(nil), -//FeeAdjustments: []sdk.Rat{sdk.ZeroRat()}, -//PrevBondedShares: sdk.ZeroRat(), +//FeeAdjustments: []sdk.Dec{sdk.ZeroDec()}, +//PrevBondedShares: sdk.ZeroDec(), //} //} @@ -85,8 +85,8 @@ package stake //// Used in calculation of fee shares, added to a queue for each block where a power change occures //type PowerChange struct { //Height int64 `json:"height"` // block height at change -//Power sdk.Rat `json:"power"` // total power at change -//PrevPower sdk.Rat `json:"prev_power"` // total power at previous height-1 +//Power sdk.Dec `json:"power"` // total power at change +//PrevPower sdk.Dec `json:"prev_power"` // total power at previous height-1 //FeesIn sdk.Coins `json:"fees_in"` // fees in at block height //PrevFeePool sdk.Coins `json:"prev_fee_pool"` // total fees in at previous block height //} diff --git a/x/gov/genesis.go b/x/gov/genesis.go index 78b39ff1c..15f952c00 100644 --- a/x/gov/genesis.go +++ b/x/gov/genesis.go @@ -33,9 +33,9 @@ func DefaultGenesisState() GenesisState { VotingPeriod: 200, }, TallyingProcedure: TallyingProcedure{ - Threshold: sdk.NewRat(1, 2), - Veto: sdk.NewRat(1, 3), - GovernancePenalty: sdk.NewRat(1, 100), + Threshold: sdk.NewDecWithPrec(5, 1), + Veto: sdk.NewDecWithPrec(334, 3), + GovernancePenalty: sdk.NewDecWithPrec(1, 2), }, } } diff --git a/x/gov/procedures.go b/x/gov/procedures.go index f46c2149f..f74091c74 100644 --- a/x/gov/procedures.go +++ b/x/gov/procedures.go @@ -12,9 +12,9 @@ type DepositProcedure struct { // Procedure around Tallying votes in governance type TallyingProcedure struct { - Threshold sdk.Rat `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 - Veto sdk.Rat `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 - GovernancePenalty sdk.Rat `json:"governance_penalty"` // Penalty if validator does not vote + Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5 + Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3 + GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote } // Procedure around Voting in governance diff --git a/x/gov/proposals.go b/x/gov/proposals.go index 0a7f5de70..f05dabd08 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -297,19 +297,19 @@ func (status ProposalStatus) Format(s fmt.State, verb rune) { //----------------------------------------------------------- // Tally Results type TallyResult struct { - Yes sdk.Rat `json:"yes"` - Abstain sdk.Rat `json:"abstain"` - No sdk.Rat `json:"no"` - NoWithVeto sdk.Rat `json:"no_with_veto"` + Yes sdk.Dec `json:"yes"` + Abstain sdk.Dec `json:"abstain"` + No sdk.Dec `json:"no"` + NoWithVeto sdk.Dec `json:"no_with_veto"` } // checks if two proposals are equal func EmptyTallyResult() TallyResult { return TallyResult{ - Yes: sdk.ZeroRat(), - Abstain: sdk.ZeroRat(), - No: sdk.ZeroRat(), - NoWithVeto: sdk.ZeroRat(), + Yes: sdk.ZeroDec(), + Abstain: sdk.ZeroDec(), + No: sdk.ZeroDec(), + NoWithVeto: sdk.ZeroDec(), } } diff --git a/x/gov/tally.go b/x/gov/tally.go index f8a341e1e..fc5b4317b 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -7,20 +7,20 @@ import ( // validatorGovInfo used for tallying type validatorGovInfo struct { Address sdk.AccAddress // sdk.AccAddress of the validator owner - Power sdk.Rat // Power of a Validator - DelegatorShares sdk.Rat // Total outstanding delegator shares - Minus sdk.Rat // Minus of validator, used to compute validator's voting power + Power sdk.Dec // Power of a Validator + DelegatorShares sdk.Dec // Total outstanding delegator shares + Minus sdk.Dec // Minus of validator, used to compute validator's voting power Vote VoteOption // Vote of the validator } func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.AccAddress) { - results := make(map[VoteOption]sdk.Rat) - results[OptionYes] = sdk.ZeroRat() - results[OptionAbstain] = sdk.ZeroRat() - results[OptionNo] = sdk.ZeroRat() - results[OptionNoWithVeto] = sdk.ZeroRat() + results := make(map[VoteOption]sdk.Dec) + results[OptionYes] = sdk.ZeroDec() + results[OptionAbstain] = sdk.ZeroDec() + results[OptionNo] = sdk.ZeroDec() + results[OptionNoWithVeto] = sdk.ZeroDec() - totalVotingPower := sdk.ZeroRat() + totalVotingPower := sdk.ZeroDec() currValidators := make(map[string]validatorGovInfo) keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) { @@ -28,7 +28,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall Address: validator.GetOwner(), Power: validator.GetPower(), DelegatorShares: validator.GetDelegatorShares(), - Minus: sdk.ZeroRat(), + Minus: sdk.ZeroDec(), Vote: OptionEmpty, } return false @@ -91,7 +91,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall } // If no one votes, proposal fails - if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroRat()) { + if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) { return false, tallyResults, nonVoting } // If more than 1/3 of voters veto, proposal fails diff --git a/x/gov/test_common.go b/x/gov/test_common.go index df66fa40c..5e7977b50 100644 --- a/x/gov/test_common.go +++ b/x/gov/test_common.go @@ -64,7 +64,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk mapp.InitChainer(ctx, req) stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000) validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis) if err != nil { diff --git a/x/params/keeper.go b/x/params/keeper.go index 8817b7c6c..69bcc05ea 100644 --- a/x/params/keeper.go +++ b/x/params/keeper.go @@ -183,8 +183,8 @@ func (k Getter) GetUint(ctx sdk.Context, key string) (res sdk.Uint, err error) { return } -// GetRat is helper function for rat params -func (k Getter) GetRat(ctx sdk.Context, key string) (res sdk.Rat, err error) { +// GetDec is helper function for decimal params +func (k Getter) GetDec(ctx sdk.Context, key string) (res sdk.Dec, err error) { store := ctx.KVStore(k.k.key) bz := store.Get([]byte(key)) err = k.k.cdc.UnmarshalBinary(bz, &res) @@ -301,8 +301,8 @@ func (k Getter) GetUintWithDefault(ctx sdk.Context, key string, def sdk.Uint) (r return } -// GetRatWithDefault is helper function for sdk.Rat params with default value -func (k Getter) GetRatWithDefault(ctx sdk.Context, key string, def sdk.Rat) (res sdk.Rat) { +// GetDecWithDefault is helper function for sdk.Dec params with default value +func (k Getter) GetDecWithDefault(ctx sdk.Context, key string, def sdk.Dec) (res sdk.Dec) { store := ctx.KVStore(k.k.key) bz := store.Get([]byte(key)) if bz == nil { @@ -397,8 +397,8 @@ func (k Setter) SetUint(ctx sdk.Context, key string, param sdk.Uint) { } } -// SetRat is helper function for rat params -func (k Setter) SetRat(ctx sdk.Context, key string, param sdk.Rat) { +// SetDec is helper function for decimal params +func (k Setter) SetDec(ctx sdk.Context, key string, param sdk.Dec) { if err := k.k.set(ctx, key, param); err != nil { panic(err) } diff --git a/x/params/keeper_test.go b/x/params/keeper_test.go index 4bb5744ea..626d68c7d 100644 --- a/x/params/keeper_test.go +++ b/x/params/keeper_test.go @@ -94,7 +94,7 @@ func TestGetter(t *testing.T) { {"uint64", uint64(1)}, {"int", sdk.NewInt(1)}, {"uint", sdk.NewUint(1)}, - {"rat", sdk.NewRat(1)}, + {"rat", sdk.NewDec(1)}, } assert.NotPanics(t, func() { s.SetString(ctx, kvs[0].key, "test") }) @@ -107,7 +107,7 @@ func TestGetter(t *testing.T) { assert.NotPanics(t, func() { s.SetUint64(ctx, kvs[7].key, uint64(1)) }) assert.NotPanics(t, func() { s.SetInt(ctx, kvs[8].key, sdk.NewInt(1)) }) assert.NotPanics(t, func() { s.SetUint(ctx, kvs[9].key, sdk.NewUint(1)) }) - assert.NotPanics(t, func() { s.SetRat(ctx, kvs[10].key, sdk.NewRat(1)) }) + assert.NotPanics(t, func() { s.SetDec(ctx, kvs[10].key, sdk.NewDec(1)) }) var res interface{} var err error @@ -263,18 +263,18 @@ func TestGetter(t *testing.T) { assert.Equal(t, def9, res) // Rat - def10 := sdk.NewRat(0) - res, err = g.GetRat(ctx, kvs[10].key) + def10 := sdk.NewDec(0) + res, err = g.GetDec(ctx, kvs[10].key) assert.Nil(t, err) assert.Equal(t, kvs[10].param, res) - _, err = g.GetRat(ctx, "invalid") + _, err = g.GetDec(ctx, "invalid") assert.NotNil(t, err) - res = g.GetRatWithDefault(ctx, kvs[10].key, def10) + res = g.GetDecWithDefault(ctx, kvs[10].key, def10) assert.Equal(t, kvs[10].param, res) - res = g.GetRatWithDefault(ctx, "invalid", def10) + res = g.GetDecWithDefault(ctx, "invalid", def10) assert.Equal(t, def10, res) } diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 523a2e220..1e6a4e89d 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -58,7 +58,7 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer { return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { mapp.InitChainer(ctx, req) stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000) validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis) if err != nil { panic(err) @@ -109,7 +109,7 @@ func TestSlashingMsgs(t *testing.T) { validator := checkValidator(t, mapp, stakeKeeper, addr1, true) require.Equal(t, addr1, validator.Owner) require.Equal(t, sdk.Bonded, validator.Status) - require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) + require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())} // no signing info yet diff --git a/x/slashing/handler_test.go b/x/slashing/handler_test.go index 89c1e11a6..41cb5d199 100644 --- a/x/slashing/handler_test.go +++ b/x/slashing/handler_test.go @@ -20,7 +20,7 @@ func TestCannotUnrevokeUnlessRevoked(t *testing.T) { require.True(t, got.IsOK()) stake.EndBlocker(ctx, sk) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) // assert non-revoked validator can't be unrevoked got = slh(ctx, NewMsgUnrevoke(addr)) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index d3d6b06ed..68de7a43c 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -31,7 +31,7 @@ func TestHandleDoubleSign(t *testing.T) { validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) // handle a signature to set signing info keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) @@ -44,12 +44,12 @@ func TestHandleDoubleSign(t *testing.T) { // unrevoke to measure power sk.Unrevoke(ctx, val) // power should be reduced - require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower()) + require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))}) // double sign past max age keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt) - require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower()) + require.Equal(t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))), sk.Validator(ctx, addr).GetPower()) } // Test a validator through uptime, downtime, revocation, @@ -67,7 +67,7 @@ func TestHandleAbsentValidator(t *testing.T) { validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) info, found := keeper.getValidatorSigningInfo(ctx, sdk.ValAddress(val.Address())) require.False(t, found) require.Equal(t, int64(0), info.StartHeight) @@ -131,7 +131,7 @@ func TestHandleAbsentValidator(t *testing.T) { // validator should have been slashed pool = sk.GetPool(ctx) - slashAmt := sdk.NewRat(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64() + slashAmt := sdk.NewDec(amtInt).Mul(keeper.SlashFractionDowntime(ctx)).RoundInt64() require.Equal(t, int64(amtInt)-slashAmt, pool.BondedTokens.RoundInt64()) // validator start height should have been changed @@ -177,7 +177,7 @@ func TestHandleNewValidator(t *testing.T) { validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.SubRaw(amt)}}) - require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower()) + require.Equal(t, sdk.NewDec(amt), sk.Validator(ctx, addr).GetPower()) // 1000 first blocks not a validator ctx = ctx.WithBlockHeight(keeper.SignedBlocksWindow(ctx) + 1) diff --git a/x/slashing/params.go b/x/slashing/params.go index 9d1bc3960..a25d121c9 100644 --- a/x/slashing/params.go +++ b/x/slashing/params.go @@ -30,9 +30,9 @@ func (k Keeper) SignedBlocksWindow(ctx sdk.Context) int64 { // Downtime slashing thershold - default 50% func (k Keeper) MinSignedPerWindow(ctx sdk.Context) int64 { - minSignedPerWindow := k.params.GetRatWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow) + minSignedPerWindow := k.params.GetDecWithDefault(ctx, MinSignedPerWindowKey, defaultMinSignedPerWindow) signedBlocksWindow := k.SignedBlocksWindow(ctx) - return sdk.NewRat(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64() + return sdk.NewDec(signedBlocksWindow).Mul(minSignedPerWindow).RoundInt64() } // Double-sign unbond duration @@ -46,13 +46,13 @@ func (k Keeper) DowntimeUnbondDuration(ctx sdk.Context) time.Duration { } // SlashFractionDoubleSign - currently default 5% -func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Rat { - return k.params.GetRatWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign) +func (k Keeper) SlashFractionDoubleSign(ctx sdk.Context) sdk.Dec { + return k.params.GetDecWithDefault(ctx, SlashFractionDoubleSignKey, defaultSlashFractionDoubleSign) } // SlashFractionDowntime - currently default 1% -func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Rat { - return k.params.GetRatWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime) +func (k Keeper) SlashFractionDowntime(ctx sdk.Context) sdk.Dec { + return k.params.GetDecWithDefault(ctx, SlashFractionDowntimeKey, defaultSlashFractionDowntime) } // declared as var because of keeper_test.go @@ -72,9 +72,9 @@ var ( // TODO Temporarily set to 10 minutes for testnets defaultDowntimeUnbondDuration int64 = 60 * 10 - defaultMinSignedPerWindow = sdk.NewRat(1, 2) + defaultMinSignedPerWindow = sdk.NewDecWithPrec(5, 1) - defaultSlashFractionDoubleSign = sdk.NewRat(1).Quo(sdk.NewRat(20)) + defaultSlashFractionDoubleSign = sdk.NewDec(1).Quo(sdk.NewDec(20)) - defaultSlashFractionDowntime = sdk.NewRat(1).Quo(sdk.NewRat(100)) + defaultSlashFractionDowntime = sdk.NewDec(1).Quo(sdk.NewDec(100)) ) diff --git a/x/slashing/test_common.go b/x/slashing/test_common.go index 7b3ab0436..50c501d7e 100644 --- a/x/slashing/test_common.go +++ b/x/slashing/test_common.go @@ -69,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace) genesis := stake.DefaultGenesisState() - genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64()) + genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64()) _, err = stake.InitGenesis(ctx, sk, genesis) require.Nil(t, err) diff --git a/x/slashing/tick_test.go b/x/slashing/tick_test.go index 8e0d66ed6..b230f9c94 100644 --- a/x/slashing/tick_test.go +++ b/x/slashing/tick_test.go @@ -22,7 +22,7 @@ func TestBeginBlocker(t *testing.T) { validatorUpdates := stake.EndBlocker(ctx, sk) keeper.AddValidators(ctx, validatorUpdates) require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins.Sub(amt)}}) - require.True(t, sdk.NewRatFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) + require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower())) val := abci.Validator{ Address: pk.Address(), diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 4e1b2c2ac..9847ed290 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -63,7 +63,7 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer { mapp.InitChainer(ctx, req) stakeGenesis := DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(100000) validators, err := InitGenesis(ctx, keeper, stakeGenesis) if err != nil { @@ -90,14 +90,14 @@ func checkValidator(t *testing.T, mapp *mock.App, keeper Keeper, func checkDelegation( t *testing.T, mapp *mock.App, keeper Keeper, delegatorAddr, - validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Rat, + validatorAddr sdk.AccAddress, expFound bool, expShares sdk.Dec, ) { ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) delegation, found := keeper.GetDelegation(ctxCheck, delegatorAddr, validatorAddr) if expFound { require.True(t, found) - require.True(sdk.RatEq(t, expShares, delegation.Shares)) + require.True(sdk.DecEq(t, expShares, delegation.Shares)) return } @@ -138,7 +138,7 @@ func TestStakeMsgs(t *testing.T) { validator := checkValidator(t, mApp, keeper, addr1, true) require.Equal(t, addr1, validator.Owner) require.Equal(t, sdk.Bonded, validator.Status) - require.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) + require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) // addr1 create validator on behalf of addr2 createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(addr1, addr2, priv2.PubKey(), bondCoin, description) @@ -150,10 +150,10 @@ func TestStakeMsgs(t *testing.T) { validator = checkValidator(t, mApp, keeper, addr2, true) require.Equal(t, addr2, validator.Owner) require.Equal(t, sdk.Bonded, validator.Status) - require.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) + require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) // check the bond that should have been created as well - checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewRat(10)) + checkDelegation(t, mApp, keeper, addr1, addr1, true, sdk.NewDec(10)) // edit the validator description = NewDescription("bar_moniker", "", "", "") @@ -169,14 +169,14 @@ func TestStakeMsgs(t *testing.T) { mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{1}, true, priv2) mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) - checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewRat(10)) + checkDelegation(t, mApp, keeper, addr2, addr1, true, sdk.NewDec(10)) // begin unbonding - beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewRat(10)) + beginUnbondingMsg := NewMsgBeginUnbonding(addr2, addr1, sdk.NewDec(10)) mock.SignCheckDeliver(t, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []int64{1}, []int64{2}, true, priv2) // delegation should exist anymore - checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Rat{}) + checkDelegation(t, mApp, keeper, addr2, addr1, false, sdk.Dec{}) // balance should be the same because bonding not yet complete mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Minus(bondCoin)}) diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 4c86777f3..bf2df4913 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -239,27 +239,27 @@ func GetCmdBeginRedelegate(storeName string, cdc *wire.Codec) *cobra.Command { func getShares( storeName string, cdc *wire.Codec, sharesAmountStr, sharesPercentStr string, delegatorAddr, validatorAddr sdk.AccAddress, -) (sharesAmount sdk.Rat, err error) { +) (sharesAmount sdk.Dec, err error) { switch { case sharesAmountStr != "" && sharesPercentStr != "": return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") case sharesAmountStr == "" && sharesPercentStr == "": return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both") case sharesAmountStr != "": - sharesAmount, err = sdk.NewRatFromDecimal(sharesAmountStr, types.MaxBondDenominatorPrecision) + sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr) if err != nil { return sharesAmount, err } - if !sharesAmount.GT(sdk.ZeroRat()) { + if !sharesAmount.GT(sdk.ZeroDec()) { return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)") } case sharesPercentStr != "": - var sharesPercent sdk.Rat - sharesPercent, err = sdk.NewRatFromDecimal(sharesPercentStr, types.MaxBondDenominatorPrecision) + var sharesPercent sdk.Dec + sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr) if err != nil { return sharesAmount, err } - if !sharesPercent.GT(sdk.ZeroRat()) || !sharesPercent.LTE(sdk.OneRat()) { + if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) { return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)") } diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 1741f8823..b7d2b10a4 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -347,7 +347,7 @@ func delegationHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handle DelegatorAddr: delegation.DelegatorAddr, ValidatorAddr: delegation.ValidatorAddr, Height: delegation.Height, - Shares: delegation.Shares.FloatString(), + Shares: delegation.Shares.String(), } output, err := cdc.MarshalJSON(outputDelegation) diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index fbefc7f21..d8b9b6011 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/wire" authcliCtx "github.com/cosmos/cosmos-sdk/x/auth/client/context" "github.com/cosmos/cosmos-sdk/x/stake" - "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/gorilla/mux" @@ -160,7 +159,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex return } - shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision) + shares, err := sdk.NewDecFromStr(msg.SharesAmount) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) @@ -234,7 +233,7 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex return } - shares, err := sdk.NewRatFromDecimal(msg.SharesAmount, types.MaxBondDenominatorPrecision) + shares, err := sdk.NewDecFromStr(msg.SharesAmount) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Couldn't decode shares amount. Error: %s", err.Error()))) diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index da00eda0b..1a0809089 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -76,7 +76,7 @@ func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegat DelegatorAddr: delegation.DelegatorAddr, ValidatorAddr: delegation.ValidatorAddr, Height: delegation.Height, - Shares: delegation.Shares.FloatString(), + Shares: delegation.Shares.String(), } return outputDelegation, http.StatusOK, "", nil diff --git a/x/stake/genesis_test.go b/x/stake/genesis_test.go index 2febd2c6a..9cdbe1982 100644 --- a/x/stake/genesis_test.go +++ b/x/stake/genesis_test.go @@ -17,7 +17,7 @@ func TestInitGenesis(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) pool := keeper.GetPool(ctx) - pool.BondedTokens = sdk.NewRat(2) + pool.BondedTokens = sdk.NewDec(2) params := keeper.GetParams(ctx) var delegations []Delegation @@ -32,11 +32,11 @@ func TestInitGenesis(t *testing.T) { // initialize the validators validators[0].Status = sdk.Bonded - validators[0].Tokens = sdk.OneRat() - validators[0].DelegatorShares = sdk.OneRat() + validators[0].Tokens = sdk.OneDec() + validators[0].DelegatorShares = sdk.OneDec() validators[1].Status = sdk.Bonded - validators[1].Tokens = sdk.OneRat() - validators[1].DelegatorShares = sdk.OneRat() + validators[1].Tokens = sdk.OneDec() + validators[1].DelegatorShares = sdk.OneDec() genesisState = types.NewGenesisState(pool, params, validators, delegations) vals, err := InitGenesis(ctx, keeper, genesisState) @@ -69,7 +69,7 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { // Assigning 2 to the first 100 vals, 1 to the rest pool := keeper.GetPool(ctx) - pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100))) + pool.BondedTokens = sdk.NewDec(int64(200 + (size - 100))) params := keeper.GetParams(ctx) delegations := []Delegation{} @@ -80,11 +80,11 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { validators[i].Status = sdk.Bonded if i < 100 { - validators[i].Tokens = sdk.NewRat(2) - validators[i].DelegatorShares = sdk.NewRat(2) + validators[i].Tokens = sdk.NewDec(2) + validators[i].DelegatorShares = sdk.NewDec(2) } else { - validators[i].Tokens = sdk.OneRat() - validators[i].DelegatorShares = sdk.OneRat() + validators[i].Tokens = sdk.OneDec() + validators[i].DelegatorShares = sdk.OneDec() } } diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index edad64f44..a06be0f88 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -81,7 +81,7 @@ func TestValidatorByPowerIndex(t *testing.T) { require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got) // slash and revoke the first validator - keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewRat(1, 2)) + keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1)) keeper.Revoke(ctx, keep.PKs[0]) validator, found = keeper.GetValidator(ctx, validatorAddr) require.True(t, found) @@ -110,7 +110,7 @@ func TestValidatorByPowerIndex(t *testing.T) { require.Equal(t, power2, power3) // unbond self-delegation - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(1000000)) + msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(1000000)) msgCompleteUnbonding := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) @@ -138,8 +138,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, addr1, validator.Owner) assert.Equal(t, pk1, validator.PubKey) - assert.Equal(t, sdk.NewRat(10), validator.BondedTokens()) - assert.Equal(t, sdk.NewRat(10), validator.DelegatorShares) + assert.Equal(t, sdk.NewDec(10), validator.BondedTokens()) + assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares) assert.Equal(t, Description{}, validator.Description) // two validators can't have the same owner address @@ -162,8 +162,8 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, addr2, validator.Owner) assert.Equal(t, pk2, validator.PubKey) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) assert.Equal(t, Description{}, validator.Description) } @@ -182,8 +182,8 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { assert.Equal(t, sdk.Bonded, validator.Status) assert.Equal(t, validatorAddr, validator.Owner) assert.Equal(t, pk, validator.PubKey) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) assert.Equal(t, Description{}, validator.Description) // one validator cannot be created twice even from different delegator @@ -221,7 +221,7 @@ func TestIncrementsMsgDelegate(t *testing.T) { pool := keeper.GetPool(ctx) exRate := validator.DelegatorShareExRate() - require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v", exRate) + require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v", exRate) require.Equal(t, bondAmount, pool.BondedTokens.RoundInt64()) // just send the same msgbond multiple times @@ -240,7 +240,7 @@ func TestIncrementsMsgDelegate(t *testing.T) { require.True(t, found) exRate := validator.DelegatorShareExRate() - require.True(t, exRate.Equal(sdk.OneRat()), "expected exRate 1 got %v, i = %v", exRate, i) + require.True(t, exRate.Equal(sdk.OneDec()), "expected exRate 1 got %v, i = %v", exRate, i) expBond := int64(i+1) * bondAmount expDelegatorShares := int64(i+2) * bondAmount // (1 self delegation) @@ -295,7 +295,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { // just send the same msgUnbond multiple times // TODO use decimals here - unbondShares := sdk.NewRat(10) + unbondShares := sdk.NewDec(10) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) numUnbonds := 5 @@ -339,7 +339,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { initBond, } for _, c := range errorCases { - unbondShares := sdk.NewRat(int64(c)) + unbondShares := sdk.NewDec(int64(c)) msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.False(t, got.IsOK(), "expected unbond msg to fail") @@ -348,14 +348,14 @@ func TestIncrementsMsgUnbond(t *testing.T) { leftBonded := initBond - int64(numUnbonds)*unbondShares.RoundInt64() // should be unable to unbond one more than we have - unbondShares = sdk.NewRat(leftBonded + 1) + unbondShares = sdk.NewDec(leftBonded + 1) msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.False(t, got.IsOK(), "got: %v\nmsgUnbond: %v\nshares: %v\nleftBonded: %v\n", got, msgBeginUnbonding, unbondShares.String(), leftBonded) // should be able to unbond just what we have - unbondShares = sdk.NewRat(leftBonded) + unbondShares = sdk.NewDec(leftBonded) msgBeginUnbonding = NewMsgBeginUnbonding(delegatorAddr, validatorAddr, unbondShares) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), @@ -391,7 +391,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) { for i, validatorAddr := range validatorAddrs { _, found := keeper.GetValidator(ctx, validatorAddr) require.True(t, found) - msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewRat(10)) // remove delegation + msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddrs[i], validatorAddr, sdk.NewDec(10)) // remove delegation msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddrs[i], validatorAddr) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) @@ -436,7 +436,7 @@ func TestMultipleMsgDelegate(t *testing.T) { // unbond them all for i, delegatorAddr := range delegatorAddrs { - msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10)) + msgBeginUnbonding := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10)) msgCompleteUnbonding := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) got := handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) @@ -467,7 +467,7 @@ func TestRevokeValidator(t *testing.T) { validator, _ := keeper.GetValidator(ctx, validatorAddr) // unbond the validators bond portion - msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10)) + msgBeginUnbondingValidator := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10)) msgCompleteUnbondingValidator := NewMsgCompleteUnbonding(validatorAddr, validatorAddr) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingValidator, keeper) require.True(t, got.IsOK(), "expected no error") @@ -483,7 +483,7 @@ func TestRevokeValidator(t *testing.T) { require.False(t, got.IsOK(), "expected error, got %v", got) // test that the delegator can still withdraw their bonds - msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewRat(10)) + msgBeginUnbondingDelegator := NewMsgBeginUnbonding(delegatorAddr, validatorAddr, sdk.NewDec(10)) msgCompleteUnbondingDelegator := NewMsgCompleteUnbonding(delegatorAddr, validatorAddr) got = handleMsgBeginUnbonding(ctx, msgBeginUnbondingDelegator, keeper) require.True(t, got.IsOK(), "expected no error") @@ -510,7 +510,7 @@ func TestUnbondingPeriod(t *testing.T) { require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // begin unbonding - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewRat(10)) + msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr, validatorAddr, sdk.NewDec(10)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error") @@ -565,7 +565,7 @@ func TestRedelegationPeriod(t *testing.T) { bal1 := AccMapper.GetAccount(ctx, validatorAddr).GetCoins() // begin redelegate - msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10)) + msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, got.IsOK(), "expected no error, %v", got) @@ -617,12 +617,12 @@ func TestTransitiveRedelegation(t *testing.T) { require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // begin redelegate - msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewRat(10)) + msgBeginRedelegate := NewMsgBeginRedelegate(validatorAddr, validatorAddr, validatorAddr2, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, got.IsOK(), "expected no error, %v", got) // cannot redelegation to next validator while first delegation exists - msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewRat(10)) + msgBeginRedelegate = NewMsgBeginRedelegate(validatorAddr, validatorAddr2, validatorAddr3, sdk.NewDec(10)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, !got.IsOK(), "expected an error, msg: %v", msgBeginRedelegate) @@ -663,7 +663,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx))) // unbond the valdator-2 - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30)) + msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -785,7 +785,7 @@ func TestCliffValidator(t *testing.T) { require.Equal(t, validatorAddr2.Bytes(), cliffVal) // unbond valdator-2 - msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(30)) + msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewDec(30)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -798,7 +798,7 @@ func TestCliffValidator(t *testing.T) { require.Equal(t, validatorAddr3.Bytes(), cliffVal) // unbond valdator-1 - msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewRat(50)) + msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr1, validatorAddr1, sdk.NewDec(50)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") @@ -832,22 +832,22 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { ctx = ctx.WithBlockHeight(1) // begin unbonding 4 stake - msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewRat(4)) + msgBeginUnbonding := NewMsgBeginUnbonding(del, valA, sdk.NewDec(4)) got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") // begin redelegate 6 stake - msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewRat(6)) + msgBeginRedelegate := NewMsgBeginRedelegate(del, valA, valB, sdk.NewDec(6)) got = handleMsgBeginRedelegate(ctx, msgBeginRedelegate, keeper) require.True(t, got.IsOK(), "expected no error on runMsgBeginRedelegate") // destination delegation should have 6 shares delegation, found := keeper.GetDelegation(ctx, del, valB) require.True(t, found) - require.Equal(t, sdk.NewRat(6), delegation.Shares) + require.Equal(t, sdk.NewDec(6), delegation.Shares) // slash the validator by half - keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewRat(1, 2)) + keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should have been slashed by half unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA) @@ -862,16 +862,16 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { // destination delegation should have been slashed by half delegation, found = keeper.GetDelegation(ctx, del, valB) require.True(t, found) - require.Equal(t, sdk.NewRat(3), delegation.Shares) + require.Equal(t, sdk.NewDec(3), delegation.Shares) // validator power should have been reduced by half validator, found := keeper.GetValidator(ctx, valA) require.True(t, found) - require.Equal(t, sdk.NewRat(5), validator.GetPower()) + require.Equal(t, sdk.NewDec(5), validator.GetPower()) // slash the validator for an infraction committed after the unbonding and redelegation begin ctx = ctx.WithBlockHeight(3) - keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewRat(1, 2)) + keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1)) // unbonding delegation should be unchanged unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA) @@ -886,7 +886,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) { // destination delegation should be unchanged delegation, found = keeper.GetDelegation(ctx, del, valB) require.True(t, found) - require.Equal(t, sdk.NewRat(3), delegation.Shares) + require.Equal(t, sdk.NewDec(3), delegation.Shares) // validator power should have been reduced to zero // ergo validator should have been removed from the store diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 484e85ad5..4b4d267aa 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -218,7 +218,7 @@ func (k Keeper) RemoveRedelegation(ctx sdk.Context, red types.Redelegation) { // Perform a delegation, set/update everything necessary within the store. func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt sdk.Coin, - validator types.Validator, subtractAccount bool) (newShares sdk.Rat, err sdk.Error) { + validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { // Get or create the delegator delegation delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner) @@ -226,7 +226,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt delegation = types.Delegation{ DelegatorAddr: delegatorAddr, ValidatorAddr: validator.Owner, - Shares: sdk.ZeroRat(), + Shares: sdk.ZeroDec(), } } @@ -254,7 +254,7 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt // unbond the the delegation return func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, - shares sdk.Rat) (amount sdk.Rat, err sdk.Error) { + shares sdk.Dec) (amount sdk.Dec, err sdk.Error) { // check if delegation has any shares in it unbond delegation, found := k.GetDelegation(ctx, delegatorAddr, validatorAddr) @@ -312,7 +312,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr //______________________________________________________________________________________________________ // complete unbonding an unbonding record -func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error { +func (k Keeper) BeginUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error { // TODO quick fix, instead we should use an index, see https://github.com/cosmos/cosmos-sdk/issues/1402 _, found := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) @@ -365,7 +365,7 @@ func (k Keeper) CompleteUnbonding(ctx sdk.Context, delegatorAddr, validatorAddr // complete unbonding an unbonding record func (k Keeper) BeginRedelegation(ctx sdk.Context, delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) sdk.Error { + validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) sdk.Error { // check if this is a transitive redelegation if k.HasReceivingRedelegation(ctx, delegatorAddr, validatorSrcAddr) { diff --git a/x/stake/keeper/delegation_test.go b/x/stake/keeper/delegation_test.go index 5d512f0cf..4333a7494 100644 --- a/x/stake/keeper/delegation_test.go +++ b/x/stake/keeper/delegation_test.go @@ -32,7 +32,7 @@ func TestDelegation(t *testing.T) { bond1to1 := types.Delegation{ DelegatorAddr: addrDels[0], ValidatorAddr: addrVals[0], - Shares: sdk.NewRat(9), + Shares: sdk.NewDec(9), } // check the empty keeper first @@ -46,18 +46,18 @@ func TestDelegation(t *testing.T) { require.True(t, bond1to1.Equal(resBond)) // modify a records, save, and retrieve - bond1to1.Shares = sdk.NewRat(99) + bond1to1.Shares = sdk.NewDec(99) keeper.SetDelegation(ctx, bond1to1) resBond, found = keeper.GetDelegation(ctx, addrDels[0], addrVals[0]) require.True(t, found) require.True(t, bond1to1.Equal(resBond)) // add some more records - bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewRat(9), 0} - bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewRat(9), 1} - bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewRat(9), 2} - bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewRat(9), 3} - bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewRat(9), 4} + bond1to2 := types.Delegation{addrDels[0], addrVals[1], sdk.NewDec(9), 0} + bond1to3 := types.Delegation{addrDels[0], addrVals[2], sdk.NewDec(9), 1} + bond2to1 := types.Delegation{addrDels[1], addrVals[0], sdk.NewDec(9), 2} + bond2to2 := types.Delegation{addrDels[1], addrVals[1], sdk.NewDec(9), 3} + bond2to3 := types.Delegation{addrDels[1], addrVals[2], sdk.NewDec(9), 4} keeper.SetDelegation(ctx, bond1to2) keeper.SetDelegation(ctx, bond1to3) keeper.SetDelegation(ctx, bond2to1) @@ -142,7 +142,7 @@ func TestUnbondingDelegation(t *testing.T) { func TestUnbondDelegation(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 0) pool := keeper.GetPool(ctx) - pool.LooseTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) //create a validator and a delegator to that validator validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) @@ -163,8 +163,8 @@ func TestUnbondDelegation(t *testing.T) { keeper.SetDelegation(ctx, delegation) var err error - var amount sdk.Rat - amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewRat(6)) + var amount sdk.Dec + amount, err = keeper.unbond(ctx, addrDels[0], addrVals[0], sdk.NewDec(6)) require.NoError(t, err) require.Equal(t, int64(6), amount.RoundInt64()) // shares to be added to an unbonding delegation / redelegation @@ -190,8 +190,8 @@ func TestGetRedelegationsFromValidator(t *testing.T) { ValidatorDstAddr: addrVals[1], CreationHeight: 0, MinTime: time.Unix(0, 0), - SharesSrc: sdk.NewRat(5), - SharesDst: sdk.NewRat(5), + SharesSrc: sdk.NewDec(5), + SharesDst: sdk.NewDec(5), } // set and retrieve a record @@ -220,8 +220,8 @@ func TestRedelegation(t *testing.T) { ValidatorDstAddr: addrVals[1], CreationHeight: 0, MinTime: time.Unix(0, 0), - SharesSrc: sdk.NewRat(5), - SharesDst: sdk.NewRat(5), + SharesSrc: sdk.NewDec(5), + SharesDst: sdk.NewDec(5), } // test shouldn't have and redelegations @@ -242,8 +242,8 @@ func TestRedelegation(t *testing.T) { require.True(t, has) // modify a records, save, and retrieve - rd.SharesSrc = sdk.NewRat(21) - rd.SharesDst = sdk.NewRat(21) + rd.SharesSrc = sdk.NewDec(21) + rd.SharesDst = sdk.NewDec(21) keeper.SetRedelegation(ctx, rd) resBond, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) diff --git a/x/stake/keeper/keeper_test.go b/x/stake/keeper/keeper_test.go index 3f763ea25..9307ddddf 100644 --- a/x/stake/keeper/keeper_test.go +++ b/x/stake/keeper/keeper_test.go @@ -33,7 +33,7 @@ func TestPool(t *testing.T) { require.True(t, expPool.Equal(resPool)) //modify a params, save, and retrieve - expPool.BondedTokens = sdk.NewRat(777) + expPool.BondedTokens = sdk.NewDec(777) keeper.SetPool(ctx, expPool) resPool = keeper.GetPool(ctx) require.True(t, expPool.Equal(resPool)) diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 9c3311474..aeec44fae 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -69,7 +69,7 @@ func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Val } // total power from the bond -func (k Keeper) TotalPower(ctx sdk.Context) sdk.Rat { +func (k Keeper) TotalPower(ctx sdk.Context) sdk.Dec { pool := k.GetPool(ctx) return pool.BondedTokens } diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index a741b5a85..c1fabe441 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -20,15 +20,15 @@ import ( // CONTRACT: // Infraction committed at the current height or at a past height, // not at a height in the future -func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Rat) { +func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) { logger := ctx.Logger().With("module", "x/stake") - if slashFactor.LT(sdk.ZeroRat()) { + if slashFactor.LT(sdk.ZeroDec()) { panic(fmt.Errorf("attempted to slash with a negative slashFactor: %v", slashFactor)) } // Amount of slashing = slash slashFactor * power at time of infraction - slashAmount := sdk.NewRat(power).Mul(slashFactor) + slashAmount := sdk.NewDec(power).Mul(slashFactor) // ref https://github.com/cosmos/cosmos-sdk/issues/1348 // ref https://github.com/cosmos/cosmos-sdk/issues/1471 @@ -89,7 +89,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } // Cannot decrease balance below zero - tokensToBurn := sdk.MinRat(remainingSlashAmount, validator.Tokens) + tokensToBurn := sdk.MinDec(remainingSlashAmount, validator.Tokens) // Get the current pool pool := k.GetPool(ctx) @@ -150,23 +150,23 @@ func (k Keeper) setRevoked(ctx sdk.Context, pubkey crypto.PubKey, revoked bool) // (the amount actually slashed may be less if there's // insufficient stake remaining) func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation types.UnbondingDelegation, - infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) { + infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) { now := ctx.BlockHeader().Time // If unbonding started before this height, stake didn't contribute to infraction if unbondingDelegation.CreationHeight < infractionHeight { - return sdk.ZeroRat() + return sdk.ZeroDec() } if unbondingDelegation.MinTime.Before(now) { // Unbonding delegation no longer eligible for slashing, skip it // TODO Settle and delete it automatically? - return sdk.ZeroRat() + return sdk.ZeroDec() } // Calculate slash amount proportional to stake contributing to infraction - slashAmount = sdk.NewRatFromInt(unbondingDelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor) + slashAmount = sdk.NewDecFromInt(unbondingDelegation.InitialBalance.Amount).Mul(slashFactor) // Don't slash more tokens than held // Possible since the unbonding delegation may already @@ -194,23 +194,23 @@ func (k Keeper) slashUnbondingDelegation(ctx sdk.Context, unbondingDelegation ty // (the amount actually slashed may be less if there's // insufficient stake remaining) func (k Keeper) slashRedelegation(ctx sdk.Context, validator types.Validator, redelegation types.Redelegation, - infractionHeight int64, slashFactor sdk.Rat) (slashAmount sdk.Rat) { + infractionHeight int64, slashFactor sdk.Dec) (slashAmount sdk.Dec) { now := ctx.BlockHeader().Time // If redelegation started before this height, stake didn't contribute to infraction if redelegation.CreationHeight < infractionHeight { - return sdk.ZeroRat() + return sdk.ZeroDec() } if redelegation.MinTime.Before(now) { // Redelegation no longer eligible for slashing, skip it // TODO Delete it automatically? - return sdk.ZeroRat() + return sdk.ZeroDec() } // Calculate slash amount proportional to stake contributing to infraction - slashAmount = sdk.NewRatFromInt(redelegation.InitialBalance.Amount, sdk.OneInt()).Mul(slashFactor) + slashAmount = sdk.NewDecFromInt(redelegation.InitialBalance.Amount).Mul(slashFactor) // Don't slash more tokens than held // Possible since the redelegation may already diff --git a/x/stake/keeper/slash_test.go b/x/stake/keeper/slash_test.go index 878c44d1e..444858f29 100644 --- a/x/stake/keeper/slash_test.go +++ b/x/stake/keeper/slash_test.go @@ -19,7 +19,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) { params := keeper.GetParams(ctx) pool := keeper.GetPool(ctx) numVals := 3 - pool.LooseTokens = sdk.NewRat(amt * int64(numVals)) + pool.LooseTokens = sdk.NewDec(amt * int64(numVals)) // add numVals validators for i := 0; i < numVals; i++ { @@ -63,7 +63,7 @@ func TestRevocation(t *testing.T) { // tests slashUnbondingDelegation func TestSlashUnbondingDelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) // set an unbonding delegation ubd := types.UnbondingDelegation{ @@ -106,7 +106,7 @@ func TestSlashUnbondingDelegation(t *testing.T) { // tests slashRedelegation func TestSlashRedelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) // set a redelegation rd := types.Redelegation{ @@ -116,8 +116,8 @@ func TestSlashRedelegation(t *testing.T) { CreationHeight: 0, // expiration timestamp (beyond which the redelegation shouldn't be slashed) MinTime: time.Unix(0, 0), - SharesSrc: sdk.NewRat(10), - SharesDst: sdk.NewRat(10), + SharesSrc: sdk.NewDec(10), + SharesDst: sdk.NewDec(10), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 10), Balance: sdk.NewInt64Coin(params.BondDenom, 10), } @@ -127,7 +127,7 @@ func TestSlashRedelegation(t *testing.T) { del := types.Delegation{ DelegatorAddr: addrDels[0], ValidatorAddr: addrVals[1], - Shares: sdk.NewRat(10), + Shares: sdk.NewDec(10), } keeper.SetDelegation(ctx, del) @@ -172,7 +172,7 @@ func TestSlashRedelegation(t *testing.T) { func TestSlashAtFutureHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) pk := PKs[0] - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) }) } @@ -180,7 +180,7 @@ func TestSlashAtFutureHeight(t *testing.T) { func TestSlashAtCurrentHeight(t *testing.T) { ctx, keeper, _ := setupHelper(t, 10) pk := PKs[0] - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) oldPool := keeper.GetPool(ctx) validator, found := keeper.GetValidatorByPubKey(ctx, pk) @@ -193,16 +193,16 @@ func TestSlashAtCurrentHeight(t *testing.T) { newPool := keeper.GetPool(ctx) // power decreased - require.Equal(t, sdk.NewRat(5), validator.GetPower()) + require.Equal(t, sdk.NewDec(5), validator.GetPower()) // pool bonded shares decreased - require.Equal(t, sdk.NewRat(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) + require.Equal(t, sdk.NewDec(5).RoundInt64(), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64()) } // tests Slash at a previous height with an unbonding delegation func TestSlashWithUnbondingDelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) pk := PKs[0] - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) // set an unbonding delegation ubd := types.UnbondingDelegation{ @@ -239,7 +239,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { // was still bonded at the time of discovery and was slashed by half, 4 stake // bonded at the time of discovery hadn't been bonded at the time of infraction // and wasn't slashed - require.Equal(t, sdk.NewRat(7), validator.GetPower()) + require.Equal(t, sdk.NewDec(7), validator.GetPower()) // slash validator again ctx = ctx.WithBlockHeight(13) @@ -256,7 +256,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { validator, found = keeper.GetValidatorByPubKey(ctx, pk) require.True(t, found) // power decreased by 3 again - require.Equal(t, sdk.NewRat(4), validator.GetPower()) + require.Equal(t, sdk.NewDec(4), validator.GetPower()) // slash validator again // all originally bonded stake has been slashed, so this will have no effect @@ -276,7 +276,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { validator, found = keeper.GetValidatorByPubKey(ctx, pk) require.True(t, found) // power decreased by 3 again - require.Equal(t, sdk.NewRat(1), validator.GetPower()) + require.Equal(t, sdk.NewDec(1), validator.GetPower()) // slash validator again // all originally bonded stake has been slashed, so this will have no effect @@ -303,7 +303,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { func TestSlashWithRedelegation(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) pk := PKs[0] - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) // set a redelegation rd := types.Redelegation{ @@ -312,8 +312,8 @@ func TestSlashWithRedelegation(t *testing.T) { ValidatorDstAddr: addrVals[1], CreationHeight: 11, MinTime: time.Unix(0, 0), - SharesSrc: sdk.NewRat(6), - SharesDst: sdk.NewRat(6), + SharesSrc: sdk.NewDec(6), + SharesDst: sdk.NewDec(6), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6), Balance: sdk.NewInt64Coin(params.BondDenom, 6), } @@ -323,13 +323,13 @@ func TestSlashWithRedelegation(t *testing.T) { del := types.Delegation{ DelegatorAddr: addrDels[0], ValidatorAddr: addrVals[1], - Shares: sdk.NewRat(6), + Shares: sdk.NewDec(6), } keeper.SetDelegation(ctx, del) // update bonded tokens pool := keeper.GetPool(ctx) - pool.BondedTokens = pool.BondedTokens.Add(sdk.NewRat(6)) + pool.BondedTokens = pool.BondedTokens.Add(sdk.NewDec(6)) keeper.SetPool(ctx, pool) // slash validator @@ -355,13 +355,13 @@ func TestSlashWithRedelegation(t *testing.T) { // was still bonded at the time of discovery and was slashed by half, 4 stake // bonded at the time of discovery hadn't been bonded at the time of infraction // and wasn't slashed - require.Equal(t, sdk.NewRat(8), validator.GetPower()) + require.Equal(t, sdk.NewDec(8), validator.GetPower()) // slash the validator again ctx = ctx.WithBlockHeight(12) validator, found = keeper.GetValidatorByPubKey(ctx, pk) require.True(t, found) - require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) }) + require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) }) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -376,13 +376,13 @@ func TestSlashWithRedelegation(t *testing.T) { validator, found = keeper.GetValidatorByPubKey(ctx, pk) require.True(t, found) // power decreased by 4 - require.Equal(t, sdk.NewRat(4), validator.GetPower()) + require.Equal(t, sdk.NewDec(4), validator.GetPower()) // slash the validator again, by 100% ctx = ctx.WithBlockHeight(12) validator, found = keeper.GetValidatorByPubKey(ctx, pk) require.True(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) + keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -404,7 +404,7 @@ func TestSlashWithRedelegation(t *testing.T) { // validator no longer in the store _, found = keeper.GetValidatorByPubKey(ctx, pk) require.False(t, found) - keeper.Slash(ctx, pk, 10, 10, sdk.OneRat()) + keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) // read updating redelegation rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1]) @@ -424,7 +424,7 @@ func TestSlashWithRedelegation(t *testing.T) { // tests Slash at a previous height with both an unbonding delegation and a redelegation func TestSlashBoth(t *testing.T) { ctx, keeper, params := setupHelper(t, 10) - fraction := sdk.NewRat(1, 2) + fraction := sdk.NewDecWithPrec(5, 1) // set a redelegation rdA := types.Redelegation{ @@ -434,8 +434,8 @@ func TestSlashBoth(t *testing.T) { CreationHeight: 11, // expiration timestamp (beyond which the redelegation shouldn't be slashed) MinTime: time.Unix(0, 0), - SharesSrc: sdk.NewRat(6), - SharesDst: sdk.NewRat(6), + SharesSrc: sdk.NewDec(6), + SharesDst: sdk.NewDec(6), InitialBalance: sdk.NewInt64Coin(params.BondDenom, 6), Balance: sdk.NewInt64Coin(params.BondDenom, 6), } @@ -445,7 +445,7 @@ func TestSlashBoth(t *testing.T) { delA := types.Delegation{ DelegatorAddr: addrDels[0], ValidatorAddr: addrVals[1], - Shares: sdk.NewRat(6), + Shares: sdk.NewDec(6), } keeper.SetDelegation(ctx, delA) @@ -483,5 +483,5 @@ func TestSlashBoth(t *testing.T) { validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0]) require.True(t, found) // power not decreased, all stake was bonded since - require.Equal(t, sdk.NewRat(10), validator.GetPower()) + require.Equal(t, sdk.NewDec(10), validator.GetPower()) } diff --git a/x/stake/keeper/test_common.go b/x/stake/keeper/test_common.go index 010963034..0470c2898 100644 --- a/x/stake/keeper/test_common.go +++ b/x/stake/keeper/test_common.go @@ -77,10 +77,10 @@ func MakeTestCodec() *wire.Codec { // default params without inflation func ParamsNoInflation() types.Params { return types.Params{ - InflationRateChange: sdk.ZeroRat(), - InflationMax: sdk.ZeroRat(), - InflationMin: sdk.ZeroRat(), - GoalBonded: sdk.NewRat(67, 100), + InflationRateChange: sdk.ZeroDec(), + InflationMax: sdk.ZeroDec(), + InflationMin: sdk.ZeroDec(), + GoalBonded: sdk.NewDecWithPrec(67, 2), MaxValidators: 100, BondDenom: "steak", } @@ -119,7 +119,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context {keeper.GetParams(ctx).BondDenom, sdk.NewInt(initCoins)}, }) require.Nil(t, err) - pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(initCoins)) + pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(initCoins)) keeper.SetPool(ctx, pool) } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index b9e61a101..7b15a9c7f 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -20,8 +20,8 @@ func TestSetValidator(t *testing.T) { validator := types.NewValidator(addrVals[0], PKs[0], types.Description{}) validator, pool, _ = validator.AddTokensFromDel(pool, 10) require.Equal(t, sdk.Unbonded, validator.Status) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) keeper.SetPool(ctx, pool) keeper.UpdateValidator(ctx, validator) @@ -29,8 +29,8 @@ func TestSetValidator(t *testing.T) { validator, found := keeper.GetValidator(ctx, addrVals[0]) require.True(t, found) require.Equal(t, sdk.Bonded, validator.Status) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.DelegatorShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) // Check each store for being saved resVal, found := keeper.GetValidator(ctx, addrVals[0]) @@ -56,8 +56,8 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { pool := keeper.GetPool(ctx) // create a random pool - pool.LooseTokens = sdk.NewRat(10000) - pool.BondedTokens = sdk.NewRat(1234) + pool.LooseTokens = sdk.NewDec(10000) + pool.BondedTokens = sdk.NewDec(1234) keeper.SetPool(ctx, pool) // add a validator @@ -76,7 +76,7 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { require.True(t, keeper.validatorByPowerIndexExists(ctx, power)) // burn half the delegator shares - validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2))) + validator, pool, burned := validator.RemoveDelShares(pool, delSharesCreated.Quo(sdk.NewDec(2))) require.Equal(t, int64(50), burned.RoundInt64()) keeper.SetPool(ctx, pool) // update the pool keeper.UpdateValidator(ctx, validator) // update the validator, possibly kicking it out @@ -103,8 +103,8 @@ func TestCliffValidatorChange(t *testing.T) { keeper.SetParams(ctx, params) // create a random pool - pool.LooseTokens = sdk.NewRat(10000) - pool.BondedTokens = sdk.NewRat(1234) + pool.LooseTokens = sdk.NewDec(10000) + pool.BondedTokens = sdk.NewDec(1234) keeper.SetPool(ctx, pool) validators := make([]types.Validator, numVals) @@ -161,7 +161,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool) // slash the validator by 100% - keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneRat()) + keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec()) // validator should have been deleted _, found := keeper.GetValidator(ctx, addrVals[0]) require.False(t, found) @@ -178,13 +178,13 @@ func TestValidatorBasics(t *testing.T) { for i, amt := range amts { validators[i] = types.NewValidator(addrVals[i], PKs[i], types.Description{}) validators[i].Status = sdk.Unbonded - validators[i].Tokens = sdk.ZeroRat() + validators[i].Tokens = sdk.ZeroDec() validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) keeper.SetPool(ctx, pool) } - assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(8), validators[1].Tokens)) - assert.True(sdk.RatEq(t, sdk.NewRat(7), validators[2].Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(8), validators[1].Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(7), validators[2].Tokens)) // check the empty keeper first _, found := keeper.GetValidator(ctx, addrVals[0]) @@ -193,7 +193,7 @@ func TestValidatorBasics(t *testing.T) { assert.Zero(t, len(resVals)) pool = keeper.GetPool(ctx) - assert.True(sdk.RatEq(t, sdk.ZeroRat(), pool.BondedTokens)) + assert.True(sdk.DecEq(t, sdk.ZeroDec(), pool.BondedTokens)) // set and retrieve a record validators[0] = keeper.UpdateValidator(ctx, validators[0]) @@ -205,15 +205,15 @@ func TestValidatorBasics(t *testing.T) { require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) assert.Equal(t, sdk.Bonded, validators[0].Status) - assert.True(sdk.RatEq(t, sdk.NewRat(9), validators[0].BondedTokens())) + assert.True(sdk.DecEq(t, sdk.NewDec(9), validators[0].BondedTokens())) pool = keeper.GetPool(ctx) - assert.True(sdk.RatEq(t, pool.BondedTokens, validators[0].BondedTokens())) + assert.True(sdk.DecEq(t, pool.BondedTokens, validators[0].BondedTokens())) // modify a records, save, and retrieve validators[0].Status = sdk.Bonded - validators[0].Tokens = sdk.NewRat(10) - validators[0].DelegatorShares = sdk.NewRat(10) + validators[0].Tokens = sdk.NewDec(10) + validators[0].DelegatorShares = sdk.NewDec(10) validators[0] = keeper.UpdateValidator(ctx, validators[0]) resVal, found = keeper.GetValidator(ctx, addrVals[0]) require.True(t, found) @@ -256,19 +256,19 @@ func GetValidatorSortingUnmixed(t *testing.T) { for i, amt := range amts { validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) validators[i].Status = sdk.Bonded - validators[i].Tokens = sdk.NewRat(amt) - validators[i].DelegatorShares = sdk.NewRat(amt) + validators[i].Tokens = sdk.NewDec(amt) + validators[i].DelegatorShares = sdk.NewDec(amt) keeper.UpdateValidator(ctx, validators[i]) } // first make sure everything made it in to the gotValidator group resValidators := keeper.GetValidatorsByPower(ctx) assert.Equal(t, n, len(resValidators)) - assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators) assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) @@ -276,14 +276,14 @@ func GetValidatorSortingUnmixed(t *testing.T) { assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators) // test a basic increase in voting power - validators[3].Tokens = sdk.NewRat(500) + validators[3].Tokens = sdk.NewDec(500) keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) require.Equal(t, len(resValidators), n) assert.True(ValEq(t, validators[3], resValidators[0])) // test a decrease in voting power - validators[3].Tokens = sdk.NewRat(300) + validators[3].Tokens = sdk.NewDec(300) keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) require.Equal(t, len(resValidators), n) @@ -291,7 +291,7 @@ func GetValidatorSortingUnmixed(t *testing.T) { assert.True(ValEq(t, validators[4], resValidators[1])) // test equal voting power, different age - validators[3].Tokens = sdk.NewRat(200) + validators[3].Tokens = sdk.NewDec(200) ctx = ctx.WithBlockHeight(10) keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -310,8 +310,8 @@ func GetValidatorSortingUnmixed(t *testing.T) { assert.True(ValEq(t, validators[4], resValidators[1])) // change in voting power of both validators, both still in v-set, no age change - validators[3].Tokens = sdk.NewRat(300) - validators[4].Tokens = sdk.NewRat(300) + validators[3].Tokens = sdk.NewDec(300) + validators[4].Tokens = sdk.NewDec(300) keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) require.Equal(t, len(resValidators), n) @@ -338,20 +338,20 @@ func GetValidatorSortingMixed(t *testing.T) { var validators [5]types.Validator for i, amt := range amts { validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) - validators[i].DelegatorShares = sdk.NewRat(amt) + validators[i].DelegatorShares = sdk.NewDec(amt) } validators[0].Status = sdk.Bonded validators[1].Status = sdk.Bonded validators[2].Status = sdk.Bonded - validators[0].Tokens = sdk.NewRat(amts[0]) - validators[1].Tokens = sdk.NewRat(amts[1]) - validators[2].Tokens = sdk.NewRat(amts[2]) + validators[0].Tokens = sdk.NewDec(amts[0]) + validators[1].Tokens = sdk.NewDec(amts[1]) + validators[2].Tokens = sdk.NewDec(amts[2]) validators[3].Status = sdk.Bonded validators[4].Status = sdk.Bonded - validators[3].Tokens = sdk.NewRat(amts[3]) - validators[4].Tokens = sdk.NewRat(amts[4]) + validators[3].Tokens = sdk.NewDec(amts[3]) + validators[4].Tokens = sdk.NewDec(amts[4]) for i := range amts { keeper.UpdateValidator(ctx, validators[i]) @@ -375,11 +375,11 @@ func GetValidatorSortingMixed(t *testing.T) { // first make sure everything made it in to the gotValidator group resValidators := keeper.GetValidatorsByPower(ctx) assert.Equal(t, n, len(resValidators)) - assert.Equal(t, sdk.NewRat(400), resValidators[0].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(200), resValidators[1].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(100), resValidators[2].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(1), resValidators[3].BondedTokens(), "%v", resValidators) - assert.Equal(t, sdk.NewRat(0), resValidators[4].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(400), resValidators[0].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(200), resValidators[1].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators) + assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators) assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) @@ -444,7 +444,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.True(ValEq(t, validators[3], resValidators[1])) // validator 3 kicked out temporarily - validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewRat(201)) + validators[3], pool, _ = validators[3].RemoveDelShares(pool, sdk.NewDec(201)) keeper.SetPool(ctx, pool) validators[3] = keeper.UpdateValidator(ctx, validators[3]) resValidators = keeper.GetValidatorsByPower(ctx) @@ -656,7 +656,7 @@ func TestGetTendermintUpdatesSingleValueChange(t *testing.T) { // test single value change // tendermintUpdate set: {} -> {c1'} validators[0].Status = sdk.Bonded - validators[0].Tokens = sdk.NewRat(600) + validators[0].Tokens = sdk.NewDec(600) validators[0] = keeper.UpdateValidator(ctx, validators[0]) updates := keeper.GetTendermintUpdates(ctx) @@ -794,21 +794,21 @@ func TestGetTendermintUpdatesPowerDecrease(t *testing.T) { require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) // check initial power - require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[0].GetPower().RoundInt64()) - require.Equal(t, sdk.NewRat(100).RoundInt64(), validators[1].GetPower().RoundInt64()) + require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[0].GetPower().RoundInt64()) + require.Equal(t, sdk.NewDec(100).RoundInt64(), validators[1].GetPower().RoundInt64()) // test multiple value change // tendermintUpdate set: {c1, c3} -> {c1', c3'} pool := keeper.GetPool(ctx) - validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewRat(20)) - validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewRat(30)) + validators[0], pool, _ = validators[0].RemoveDelShares(pool, sdk.NewDec(20)) + validators[1], pool, _ = validators[1].RemoveDelShares(pool, sdk.NewDec(30)) keeper.SetPool(ctx, pool) validators[0] = keeper.UpdateValidator(ctx, validators[0]) validators[1] = keeper.UpdateValidator(ctx, validators[1]) // power has changed - require.Equal(t, sdk.NewRat(80).RoundInt64(), validators[0].GetPower().RoundInt64()) - require.Equal(t, sdk.NewRat(70).RoundInt64(), validators[1].GetPower().RoundInt64()) + require.Equal(t, sdk.NewDec(80).RoundInt64(), validators[0].GetPower().RoundInt64()) + require.Equal(t, sdk.NewDec(70).RoundInt64(), validators[1].GetPower().RoundInt64()) // Tendermint updates should reflect power change updates := keeper.GetTendermintUpdates(ctx) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index e4869693c..654d5560b 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -31,7 +31,7 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim pool := k.GetPool(ctx) loose := sdk.ZeroInt() - bonded := sdk.ZeroRat() + bonded := sdk.ZeroDec() am.IterateAccounts(ctx, func(acc auth.Account) bool { loose = loose.Add(acc.GetCoins().AmountOf("steak")) return false @@ -67,7 +67,7 @@ func PositivePowerInvariant(k stake.Keeper) simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { ctx := app.NewContext(false, abci.Header{}) k.IterateValidatorsBonded(ctx, func(_ int64, validator sdk.Validator) bool { - require.True(t, validator.GetPower().GT(sdk.ZeroRat()), "validator with non-positive power stored") + require.True(t, validator.GetPower().GT(sdk.ZeroDec()), "validator with non-positive power stored") return false }) } diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index e4077a749..f402d765f 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -132,7 +132,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. msg := stake.MsgBeginUnbonding{ DelegatorAddr: delegatorAddress, ValidatorAddr: validatorAddress, - SharesAmount: sdk.NewRatFromInt(amount), + SharesAmount: sdk.NewDecFromInt(amount), } require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() @@ -191,7 +191,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation DelegatorAddr: delegatorAddress, ValidatorSrcAddr: sourceValidatorAddress, ValidatorDstAddr: destValidatorAddress, - SharesAmount: sdk.NewRatFromInt(amount), + SharesAmount: sdk.NewDecFromInt(amount), } require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() @@ -247,7 +247,7 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { return false }) pool := k.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Add(sdk.NewRat(loose.Int64(), 1)) + pool.LooseTokens = pool.LooseTokens.Add(sdk.NewDec(loose.Int64())) k.SetPool(ctx, pool) } } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 77fd327a5..78111c030 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -16,12 +16,12 @@ import ( type Delegation struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` ValidatorAddr sdk.AccAddress `json:"validator_addr"` - Shares sdk.Rat `json:"shares"` + Shares sdk.Dec `json:"shares"` Height int64 `json:"height"` // Last height bond updated } type delegationValue struct { - Shares sdk.Rat + Shares sdk.Dec Height int64 } @@ -81,7 +81,7 @@ var _ sdk.Delegation = Delegation{} // nolint - for sdk.Delegation func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr } func (d Delegation) GetValidator() sdk.AccAddress { return d.ValidatorAddr } -func (d Delegation) GetBondShares() sdk.Rat { return d.Shares } +func (d Delegation) GetBondShares() sdk.Dec { return d.Shares } // HumanReadableString returns a human readable string representation of a // Delegation. An error is returned if the Delegation's delegator or validator @@ -190,8 +190,8 @@ type Redelegation struct { MinTime time.Time `json:"min_time"` // unix time for redelegation completion InitialBalance sdk.Coin `json:"initial_balance"` // initial balance when redelegation started Balance sdk.Coin `json:"balance"` // current balance - SharesSrc sdk.Rat `json:"shares_src"` // amount of source shares redelegating - SharesDst sdk.Rat `json:"shares_dst"` // amount of destination shares redelegating + SharesSrc sdk.Dec `json:"shares_src"` // amount of source shares redelegating + SharesDst sdk.Dec `json:"shares_dst"` // amount of destination shares redelegating } type redValue struct { @@ -199,8 +199,8 @@ type redValue struct { MinTime time.Time InitialBalance sdk.Coin Balance sdk.Coin - SharesSrc sdk.Rat - SharesDst sdk.Rat + SharesSrc sdk.Dec + SharesDst sdk.Dec } // return the redelegation without fields contained within the key for the store diff --git a/x/stake/types/delegation_test.go b/x/stake/types/delegation_test.go index 69823db14..5624b7101 100644 --- a/x/stake/types/delegation_test.go +++ b/x/stake/types/delegation_test.go @@ -12,19 +12,19 @@ func TestDelegationEqual(t *testing.T) { d1 := Delegation{ DelegatorAddr: addr1, ValidatorAddr: addr2, - Shares: sdk.NewRat(100), + Shares: sdk.NewDec(100), } d2 := Delegation{ DelegatorAddr: addr1, ValidatorAddr: addr2, - Shares: sdk.NewRat(100), + Shares: sdk.NewDec(100), } ok := d1.Equal(d2) require.True(t, ok) d2.ValidatorAddr = addr3 - d2.Shares = sdk.NewRat(200) + d2.Shares = sdk.NewDec(200) ok = d1.Equal(d2) require.False(t, ok) @@ -34,7 +34,7 @@ func TestDelegationHumanReadableString(t *testing.T) { d := Delegation{ DelegatorAddr: addr1, ValidatorAddr: addr2, - Shares: sdk.NewRat(100), + Shares: sdk.NewDec(100), } // NOTE: Being that the validator's keypair is random, we cannot test the @@ -58,8 +58,8 @@ func TestUnbondingDelegationEqual(t *testing.T) { require.True(t, ok) ud2.ValidatorAddr = addr3 - ud2.MinTime = time.Unix(20*20*2, 0) + ud2.MinTime = time.Unix(20*20*2, 0) ok = ud1.Equal(ud2) require.False(t, ok) } @@ -92,8 +92,8 @@ func TestRedelegationEqual(t *testing.T) { ok := r1.Equal(r2) require.True(t, ok) - r2.SharesDst = sdk.NewRat(10) - r2.SharesSrc = sdk.NewRat(20) + r2.SharesDst = sdk.NewDec(10) + r2.SharesSrc = sdk.NewDec(20) r2.MinTime = time.Unix(20*20*2, 0) ok = r1.Equal(r2) @@ -105,8 +105,8 @@ func TestRedelegationHumanReadableString(t *testing.T) { DelegatorAddr: addr1, ValidatorSrcAddr: addr2, ValidatorDstAddr: addr3, - SharesDst: sdk.NewRat(10), - SharesSrc: sdk.NewRat(20), + SharesDst: sdk.NewDec(10), + SharesSrc: sdk.NewDec(20), } // NOTE: Being that the validator's keypair is random, we cannot test the diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index b3e279c8e..1595a70d9 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -100,13 +100,6 @@ func ErrBadSharesAmount(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "shares must be > 0") } -func ErrBadSharesPrecision(codespace sdk.CodespaceType) sdk.Error { - return sdk.NewError(codespace, CodeInvalidDelegation, - fmt.Sprintf("shares denominator must be < %s, try reducing the number of decimal points", - maximumBondingRationalDenominator.String()), - ) -} - func ErrBadSharesPercent(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "shares percent must be >0 and <=1") } diff --git a/x/stake/types/inflation_test.go b/x/stake/types/inflation_test.go index 0114b1e05..fd181af3c 100644 --- a/x/stake/types/inflation_test.go +++ b/x/stake/types/inflation_test.go @@ -23,30 +23,30 @@ func TestGetInflation(t *testing.T) { tests := []struct { name string setBondedTokens, setLooseTokens, - setInflation, expectedChange sdk.Rat + setInflation, expectedChange sdk.Dec }{ // with 0% bonded atom supply the inflation should increase by InflationRateChange - {"test 1", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), params.InflationRateChange.Quo(hrsPerYrRat).Round(precision)}, + {"test 1", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(hrsPerYrDec)}, // 100% bonded, starting at 20% inflation and being reduced // (1 - (1/0.67))*(0.13/8667) - {"test 2", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), - sdk.OneRat().Sub(sdk.OneRat().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, + {"test 2", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), + sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)}, // 50% bonded, starting at 10% inflation and being increased - {"test 3", sdk.OneRat(), sdk.OneRat(), sdk.NewRat(10, 100), - sdk.OneRat().Sub(sdk.NewRat(1, 2).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrRat).Round(precision)}, + {"test 3", sdk.OneDec(), sdk.OneDec(), sdk.NewDecWithPrec(10, 2), + sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(hrsPerYrDec)}, // test 7% minimum stop (testing with 100% bonded) - {"test 4", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(7, 100), sdk.ZeroRat()}, - {"test 5", sdk.OneRat(), sdk.ZeroRat(), sdk.NewRat(70001, 1000000), sdk.NewRat(-1, 1000000)}, + {"test 4", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()}, + {"test 5", sdk.OneDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(70001, 6), sdk.NewDecWithPrec(-1, 6)}, // test 20% maximum stop (testing with 0% bonded) - {"test 6", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(20, 100), sdk.ZeroRat()}, - {"test 7", sdk.ZeroRat(), sdk.ZeroRat(), sdk.NewRat(199999, 1000000), sdk.NewRat(1, 1000000)}, + {"test 6", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()}, + {"test 7", sdk.ZeroDec(), sdk.ZeroDec(), sdk.NewDecWithPrec(199999, 6), sdk.NewDecWithPrec(1, 6)}, // perfect balance shouldn't change inflation - {"test 8", sdk.NewRat(67), sdk.NewRat(33), sdk.NewRat(15, 100), sdk.ZeroRat()}, + {"test 8", sdk.NewDec(67), sdk.NewDec(33), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()}, } for _, tc := range tests { pool.BondedTokens, pool.LooseTokens = tc.setBondedTokens, tc.setLooseTokens @@ -67,77 +67,80 @@ func TestProcessProvisions(t *testing.T) { var ( initialTotalTokens int64 = 550000000 - cumulativeExpProvs = sdk.ZeroRat() + cumulativeExpProvs = sdk.ZeroDec() ) - pool.LooseTokens = sdk.NewRat(initialTotalTokens) + pool.LooseTokens = sdk.NewDec(initialTotalTokens) // process the provisions for a year for hr := 0; hr < 100; hr++ { - var expProvisions sdk.Rat + var expProvisions sdk.Dec _, expProvisions, pool = updateProvisions(t, pool, params, hr) cumulativeExpProvs = cumulativeExpProvs.Add(expProvisions) } //get the pool and do the final value checks from checkFinalPoolValues - checkFinalPoolValues(t, pool, sdk.NewRat(initialTotalTokens), cumulativeExpProvs) + checkFinalPoolValues(t, pool, sdk.NewDec(initialTotalTokens), cumulativeExpProvs) } //_________________________________________________________________________________________ ////////////////////////////////HELPER FUNCTIONS BELOW///////////////////////////////////// // Final check on the global pool values for what the total tokens accumulated from each hour of provisions -func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Rat) { +func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs sdk.Dec) { calculatedTotalTokens := initialTotalTokens.Add(cumulativeExpProvs) - require.True(sdk.RatEq(t, calculatedTotalTokens, pool.TokenSupply())) + require.True(sdk.DecEq(t, calculatedTotalTokens, pool.TokenSupply())) } // Processes provisions are added to the pool correctly every hour // Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests -func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Rat, sdk.Rat, Pool) { +func updateProvisions(t *testing.T, pool Pool, params Params, hr int) (sdk.Dec, sdk.Dec, Pool) { expInflation := pool.NextInflation(params) - expProvisions := expInflation.Mul(pool.TokenSupply().Round(precision)).Quo(hrsPerYrRat) + expProvisions := expInflation.Mul(pool.TokenSupply()).Quo(hrsPerYrDec) startTotalSupply := pool.TokenSupply() pool = pool.ProcessProvisions(params) //check provisions were added to pool - require.True(sdk.RatEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply())) + require.True(sdk.DecEq(t, startTotalSupply.Add(expProvisions), pool.TokenSupply())) return expInflation, expProvisions, pool } // Checks that The inflation will correctly increase or decrease after an update to the pool // nolint: gocyclo -func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Rat, msg string) { +func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation sdk.Dec, msg string) { inflationChange := updatedInflation.Sub(previousInflation) switch { //BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation - case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)): - require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg) + case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.LT(sdk.NewDecWithPrec(20, 2)): + require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg) //BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio - case pool.BondedRatio().LT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(20, 100)): - if previousInflation.Equal(sdk.NewRat(20, 100)) { + case pool.BondedRatio().LT(sdk.NewDecWithPrec(67, 2)) && updatedInflation.Equal(sdk.NewDecWithPrec(20, 2)): + if previousInflation.Equal(sdk.NewDecWithPrec(20, 2)) { require.Equal(t, true, inflationChange.IsZero(), msg) //This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%) } else { - require.Equal(t, true, inflationChange.GT(sdk.ZeroRat()), msg) + require.Equal(t, true, inflationChange.GT(sdk.ZeroDec()), msg) } //ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7% - case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.LT(sdk.NewRat(20, 100)) && updatedInflation.GT(sdk.NewRat(7, 100)): - require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg) + case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) && + updatedInflation.LT(sdk.NewDecWithPrec(20, 2)) && updatedInflation.GT(sdk.NewDecWithPrec(7, 2)): + require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg) //ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%. - case pool.BondedRatio().GT(sdk.NewRat(67, 100)) && updatedInflation.Equal(sdk.NewRat(7, 100)): - if previousInflation.Equal(sdk.NewRat(7, 100)) { + case pool.BondedRatio().GT(sdk.NewDecWithPrec(67, 2)) && + updatedInflation.Equal(sdk.NewDecWithPrec(7, 2)): + + if previousInflation.Equal(sdk.NewDecWithPrec(7, 2)) { require.Equal(t, true, inflationChange.IsZero(), msg) //This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%) } else { - require.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg) + require.Equal(t, true, inflationChange.LT(sdk.ZeroDec()), msg) } } } diff --git a/x/stake/types/msg.go b/x/stake/types/msg.go index 27edad5dd..282000294 100644 --- a/x/stake/types/msg.go +++ b/x/stake/types/msg.go @@ -1,7 +1,6 @@ package types import ( - "math" "reflect" sdk "github.com/cosmos/cosmos-sdk/types" @@ -11,18 +10,11 @@ import ( // name to idetify transaction types const MsgType = "stake" -// Maximum amount of decimal points in the decimal representation of rationals -// used in MsgBeginUnbonding / MsgBeginRedelegate -const MaxBondDenominatorPrecision = 8 - // Verify interface at compile time var _, _, _ sdk.Msg = &MsgCreateValidator{}, &MsgEditValidator{}, &MsgDelegate{} var _, _ sdk.Msg = &MsgBeginUnbonding{}, &MsgCompleteUnbonding{} var _, _ sdk.Msg = &MsgBeginRedelegate{}, &MsgCompleteRedelegate{} -// Initialize Int for the denominator -var maximumBondingRationalDenominator = sdk.NewInt(int64(math.Pow10(MaxBondDenominatorPrecision))) - //______________________________________________________________________ // MsgCreateValidator - struct for unbonding transactions @@ -211,11 +203,11 @@ type MsgBeginRedelegate struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` ValidatorSrcAddr sdk.AccAddress `json:"validator_src_addr"` ValidatorDstAddr sdk.AccAddress `json:"validator_dst_addr"` - SharesAmount sdk.Rat `json:"shares_amount"` + SharesAmount sdk.Dec `json:"shares_amount"` } func NewMsgBeginRedelegate(delegatorAddr, validatorSrcAddr, - validatorDstAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginRedelegate { + validatorDstAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginRedelegate { return MsgBeginRedelegate{ DelegatorAddr: delegatorAddr, @@ -261,12 +253,9 @@ func (msg MsgBeginRedelegate) ValidateBasic() sdk.Error { if msg.ValidatorDstAddr == nil { return ErrNilValidatorAddr(DefaultCodespace) } - if msg.SharesAmount.LTE(sdk.ZeroRat()) { + if msg.SharesAmount.LTE(sdk.ZeroDec()) { return ErrBadSharesAmount(DefaultCodespace) } - if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) { - return ErrBadSharesPrecision(DefaultCodespace) - } return nil } @@ -322,10 +311,10 @@ func (msg MsgCompleteRedelegate) ValidateBasic() sdk.Error { type MsgBeginUnbonding struct { DelegatorAddr sdk.AccAddress `json:"delegator_addr"` ValidatorAddr sdk.AccAddress `json:"validator_addr"` - SharesAmount sdk.Rat `json:"shares_amount"` + SharesAmount sdk.Dec `json:"shares_amount"` } -func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Rat) MsgBeginUnbonding { +func NewMsgBeginUnbonding(delegatorAddr, validatorAddr sdk.AccAddress, sharesAmount sdk.Dec) MsgBeginUnbonding { return MsgBeginUnbonding{ DelegatorAddr: delegatorAddr, ValidatorAddr: validatorAddr, @@ -362,12 +351,9 @@ func (msg MsgBeginUnbonding) ValidateBasic() sdk.Error { if msg.ValidatorAddr == nil { return ErrNilValidatorAddr(DefaultCodespace) } - if msg.SharesAmount.LTE(sdk.ZeroRat()) { + if msg.SharesAmount.LTE(sdk.ZeroDec()) { return ErrBadSharesAmount(DefaultCodespace) } - if msg.SharesAmount.Denom().GT(maximumBondingRationalDenominator) { - return ErrBadSharesPrecision(DefaultCodespace) - } return nil } diff --git a/x/stake/types/msg_test.go b/x/stake/types/msg_test.go index 82f92d9f3..2be34fb20 100644 --- a/x/stake/types/msg_test.go +++ b/x/stake/types/msg_test.go @@ -143,15 +143,15 @@ func TestMsgBeginRedelegate(t *testing.T) { delegatorAddr sdk.AccAddress validatorSrcAddr sdk.AccAddress validatorDstAddr sdk.AccAddress - sharesAmount sdk.Rat + sharesAmount sdk.Dec expectPass bool }{ - {"regular", addr1, addr2, addr3, sdk.NewRat(1, 10), true}, - {"negative decimal", addr1, addr2, addr3, sdk.NewRat(-1, 10), false}, - {"zero amount", addr1, addr2, addr3, sdk.ZeroRat(), false}, - {"empty delegator", emptyAddr, addr1, addr3, sdk.NewRat(1, 10), false}, - {"empty source validator", addr1, emptyAddr, addr3, sdk.NewRat(1, 10), false}, - {"empty destination validator", addr1, addr2, emptyAddr, sdk.NewRat(1, 10), false}, + {"regular", addr1, addr2, addr3, sdk.NewDecWithPrec(1, 1), true}, + {"negative decimal", addr1, addr2, addr3, sdk.NewDecWithPrec(-1, 1), false}, + {"zero amount", addr1, addr2, addr3, sdk.ZeroDec(), false}, + {"empty delegator", emptyAddr, addr1, addr3, sdk.NewDecWithPrec(1, 1), false}, + {"empty source validator", addr1, emptyAddr, addr3, sdk.NewDecWithPrec(1, 1), false}, + {"empty destination validator", addr1, addr2, emptyAddr, sdk.NewDecWithPrec(1, 1), false}, } for _, tc := range tests { @@ -195,14 +195,14 @@ func TestMsgBeginUnbonding(t *testing.T) { name string delegatorAddr sdk.AccAddress validatorAddr sdk.AccAddress - sharesAmount sdk.Rat + sharesAmount sdk.Dec expectPass bool }{ - {"regular", addr1, addr2, sdk.NewRat(1, 10), true}, - {"negative decimal", addr1, addr2, sdk.NewRat(-1, 10), false}, - {"zero amount", addr1, addr2, sdk.ZeroRat(), false}, - {"empty delegator", emptyAddr, addr1, sdk.NewRat(1, 10), false}, - {"empty validator", addr1, emptyAddr, sdk.NewRat(1, 10), false}, + {"regular", addr1, addr2, sdk.NewDecWithPrec(1, 1), true}, + {"negative decimal", addr1, addr2, sdk.NewDecWithPrec(-1, 1), false}, + {"zero amount", addr1, addr2, sdk.ZeroDec(), false}, + {"empty delegator", emptyAddr, addr1, sdk.NewDecWithPrec(1, 1), false}, + {"empty validator", addr1, emptyAddr, sdk.NewDecWithPrec(1, 1), false}, } for _, tc := range tests { diff --git a/x/stake/types/params.go b/x/stake/types/params.go index 0ae1ade09..f297f3105 100644 --- a/x/stake/types/params.go +++ b/x/stake/types/params.go @@ -13,10 +13,10 @@ const defaultUnbondingTime time.Duration = 60 * 60 * 24 * 3 * time.Second // Params defines the high level settings for staking type Params struct { - InflationRateChange sdk.Rat `json:"inflation_rate_change"` // maximum annual change in inflation rate - InflationMax sdk.Rat `json:"inflation_max"` // maximum inflation rate - InflationMin sdk.Rat `json:"inflation_min"` // minimum inflation rate - GoalBonded sdk.Rat `json:"goal_bonded"` // Goal of percent bonded atoms + InflationRateChange sdk.Dec `json:"inflation_rate_change"` // maximum annual change in inflation rate + InflationMax sdk.Dec `json:"inflation_max"` // maximum inflation rate + InflationMin sdk.Dec `json:"inflation_min"` // minimum inflation rate + GoalBonded sdk.Dec `json:"goal_bonded"` // Goal of percent bonded atoms UnbondingTime time.Duration `json:"unbonding_time"` @@ -34,10 +34,10 @@ func (p Params) Equal(p2 Params) bool { // DefaultParams returns a default set of parameters. func DefaultParams() Params { return Params{ - InflationRateChange: sdk.NewRat(13, 100), - InflationMax: sdk.NewRat(20, 100), - InflationMin: sdk.NewRat(7, 100), - GoalBonded: sdk.NewRat(67, 100), + InflationRateChange: sdk.NewDecWithPrec(13, 2), + InflationMax: sdk.NewDecWithPrec(20, 2), + InflationMin: sdk.NewDecWithPrec(7, 2), + GoalBonded: sdk.NewDecWithPrec(67, 2), UnbondingTime: defaultUnbondingTime, MaxValidators: 100, BondDenom: "steak", diff --git a/x/stake/types/pool.go b/x/stake/types/pool.go index 5aab4294b..d59c1ed25 100644 --- a/x/stake/types/pool.go +++ b/x/stake/types/pool.go @@ -10,15 +10,15 @@ import ( // Pool - dynamic parameters of the current state type Pool struct { - LooseTokens sdk.Rat `json:"loose_tokens"` // tokens which are not bonded in a validator - BondedTokens sdk.Rat `json:"bonded_tokens"` // reserve of bonded tokens - InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed - Inflation sdk.Rat `json:"inflation"` // current annual inflation rate + LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator + BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens + InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time + Inflation sdk.Dec `json:"inflation"` // current annual inflation rate DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily) // Fee Related - PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations + PrevBondedShares sdk.Dec `json:"prev_bonded_shares"` // last recorded bonded shares - for fee calculations } // nolint @@ -31,48 +31,48 @@ func (p Pool) Equal(p2 Pool) bool { // initial pool for testing func InitialPool() Pool { return Pool{ - LooseTokens: sdk.ZeroRat(), - BondedTokens: sdk.ZeroRat(), + LooseTokens: sdk.ZeroDec(), + BondedTokens: sdk.ZeroDec(), InflationLastTime: time.Unix(0, 0), - Inflation: sdk.NewRat(7, 100), + Inflation: sdk.NewDecWithPrec(7, 2), DateLastCommissionReset: 0, - PrevBondedShares: sdk.ZeroRat(), + PrevBondedShares: sdk.ZeroDec(), } } //____________________________________________________________________ // Sum total of all staking tokens in the pool -func (p Pool) TokenSupply() sdk.Rat { +func (p Pool) TokenSupply() sdk.Dec { return p.LooseTokens.Add(p.BondedTokens) } //____________________________________________________________________ // get the bond ratio of the global state -func (p Pool) BondedRatio() sdk.Rat { +func (p Pool) BondedRatio() sdk.Dec { supply := p.TokenSupply() - if supply.GT(sdk.ZeroRat()) { + if supply.GT(sdk.ZeroDec()) { return p.BondedTokens.Quo(supply) } - return sdk.ZeroRat() + return sdk.ZeroDec() } //_______________________________________________________________________ -func (p Pool) looseTokensToBonded(bondedTokens sdk.Rat) Pool { +func (p Pool) looseTokensToBonded(bondedTokens sdk.Dec) Pool { p.BondedTokens = p.BondedTokens.Add(bondedTokens) p.LooseTokens = p.LooseTokens.Sub(bondedTokens) - if p.LooseTokens.LT(sdk.ZeroRat()) { + if p.LooseTokens.LT(sdk.ZeroDec()) { panic(fmt.Sprintf("sanity check: loose tokens negative, pool: %v", p)) } return p } -func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool { +func (p Pool) bondedTokensToLoose(bondedTokens sdk.Dec) Pool { p.BondedTokens = p.BondedTokens.Sub(bondedTokens) p.LooseTokens = p.LooseTokens.Add(bondedTokens) - if p.BondedTokens.LT(sdk.ZeroRat()) { + if p.BondedTokens.LT(sdk.ZeroDec()) { panic(fmt.Sprintf("sanity check: bonded tokens negative, pool: %v", p)) } return p @@ -82,14 +82,14 @@ func (p Pool) bondedTokensToLoose(bondedTokens sdk.Rat) Pool { // Inflation const precision = 10000 // increased to this precision for accuracy -var hrsPerYrRat = sdk.NewRat(8766) // as defined by a julian year of 365.25 days +var hrsPerYrDec = sdk.NewDec(8766) // as defined by a julian year of 365.25 days // process provisions for an hour period func (p Pool) ProcessProvisions(params Params) Pool { p.Inflation = p.NextInflation(params) provisions := p.Inflation. - Mul(p.TokenSupply().Round(precision)). - Quo(hrsPerYrRat) + Mul(p.TokenSupply()). + Quo(hrsPerYrDec) // TODO add to the fees provisions p.LooseTokens = p.LooseTokens.Add(provisions) @@ -97,7 +97,7 @@ func (p Pool) ProcessProvisions(params Params) Pool { } // get the next inflation rate for the hour -func (p Pool) NextInflation(params Params) (inflation sdk.Rat) { +func (p Pool) NextInflation(params Params) (inflation sdk.Dec) { // The target annual inflation rate is recalculated for each previsions cycle. The // inflation is also subject to a rate change (positive or negative) depending on @@ -106,11 +106,11 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) { // 7% and 20%. // (1 - bondedRatio/GoalBonded) * InflationRateChange - inflationRateChangePerYear := sdk.OneRat(). - Sub(p.BondedRatio().Round(precision). + inflationRateChangePerYear := sdk.OneDec(). + Sub(p.BondedRatio(). Quo(params.GoalBonded)). Mul(params.InflationRateChange) - inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrRat) + inflationRateChange := inflationRateChangePerYear.Quo(hrsPerYrDec) // increase the new annual inflation for this next cycle inflation = p.Inflation.Add(inflationRateChange) @@ -121,5 +121,5 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Rat) { inflation = params.InflationMin } - return inflation.Round(precision) + return inflation } diff --git a/x/stake/types/pool_test.go b/x/stake/types/pool_test.go index 43a2eac06..4541edd3d 100644 --- a/x/stake/types/pool_test.go +++ b/x/stake/types/pool_test.go @@ -11,28 +11,28 @@ func TestPoolEqual(t *testing.T) { p1 := InitialPool() p2 := InitialPool() require.True(t, p1.Equal(p2)) - p2.BondedTokens = sdk.NewRat(3) + p2.BondedTokens = sdk.NewDec(3) require.False(t, p1.Equal(p2)) } func TestAddBondedTokens(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) - pool.BondedTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) + pool.BondedTokens = sdk.NewDec(10) - pool = pool.looseTokensToBonded(sdk.NewRat(10)) + pool = pool.looseTokensToBonded(sdk.NewDec(10)) - require.True(sdk.RatEq(t, sdk.NewRat(20), pool.BondedTokens)) - require.True(sdk.RatEq(t, sdk.NewRat(0), pool.LooseTokens)) + require.True(sdk.DecEq(t, sdk.NewDec(20), pool.BondedTokens)) + require.True(sdk.DecEq(t, sdk.NewDec(0), pool.LooseTokens)) } func TestRemoveBondedTokens(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) - pool.BondedTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) + pool.BondedTokens = sdk.NewDec(10) - pool = pool.bondedTokensToLoose(sdk.NewRat(5)) + pool = pool.bondedTokensToLoose(sdk.NewDec(5)) - require.True(sdk.RatEq(t, sdk.NewRat(5), pool.BondedTokens)) - require.True(sdk.RatEq(t, sdk.NewRat(15), pool.LooseTokens)) + require.True(sdk.DecEq(t, sdk.NewDec(5), pool.BondedTokens)) + require.True(sdk.DecEq(t, sdk.NewDec(15), pool.LooseTokens)) } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 837b8f8e8..c9626b5ec 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -26,21 +26,21 @@ type Validator struct { Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) - Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation) - DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators + Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) + DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators Description Description `json:"description"` // description terms for the validator BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer - Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators - CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge - CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission - CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) + Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators + CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge + CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission + CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) // fee related - LastBondedTokens sdk.Rat `json:"prev_bonded_tokens"` // Previous bonded tokens held + LastBondedTokens sdk.Dec `json:"prev_bonded_tokens"` // Previous bonded tokens held } // NewValidator - initialize a new validator @@ -50,17 +50,17 @@ func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Descri PubKey: pubKey, Revoked: false, Status: sdk.Unbonded, - Tokens: sdk.ZeroRat(), - DelegatorShares: sdk.ZeroRat(), + Tokens: sdk.ZeroDec(), + DelegatorShares: sdk.ZeroDec(), Description: description, BondHeight: int64(0), BondIntraTxCounter: int16(0), ProposerRewardPool: sdk.Coins{}, - Commission: sdk.ZeroRat(), - CommissionMax: sdk.ZeroRat(), - CommissionChangeRate: sdk.ZeroRat(), - CommissionChangeToday: sdk.ZeroRat(), - LastBondedTokens: sdk.ZeroRat(), + Commission: sdk.ZeroDec(), + CommissionMax: sdk.ZeroDec(), + CommissionChangeRate: sdk.ZeroDec(), + CommissionChangeToday: sdk.ZeroDec(), + LastBondedTokens: sdk.ZeroDec(), } } @@ -69,17 +69,17 @@ type validatorValue struct { PubKey crypto.PubKey Revoked bool Status sdk.BondStatus - Tokens sdk.Rat - DelegatorShares sdk.Rat + Tokens sdk.Dec + DelegatorShares sdk.Dec Description Description BondHeight int64 BondIntraTxCounter int16 ProposerRewardPool sdk.Coins - Commission sdk.Rat - CommissionMax sdk.Rat - CommissionChangeRate sdk.Rat - CommissionChangeToday sdk.Rat - LastBondedTokens sdk.Rat + Commission sdk.Dec + CommissionMax sdk.Dec + CommissionChangeRate sdk.Dec + CommissionChangeToday sdk.Dec + LastBondedTokens sdk.Dec } // return the redelegation without fields contained within the key for the store @@ -159,8 +159,8 @@ func (v Validator) HumanReadableString() (string, error) { resp += fmt.Sprintf("Validator: %s\n", bechVal) resp += fmt.Sprintf("Revoked: %v\n", v.Revoked) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) - resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.FloatString()) - resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.FloatString()) + resp += fmt.Sprintf("Tokens: %s\n", v.Tokens.String()) + resp += fmt.Sprintf("Delegator Shares: %s\n", v.DelegatorShares.String()) resp += fmt.Sprintf("Description: %s\n", v.Description) resp += fmt.Sprintf("Bond Height: %d\n", v.BondHeight) resp += fmt.Sprintf("Proposer Reward Pool: %s\n", v.ProposerRewardPool.String()) @@ -182,21 +182,21 @@ type BechValidator struct { Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) - Tokens sdk.Rat `json:"tokens"` // delegated tokens (incl. self-delegation) - DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators + Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) + DelegatorShares sdk.Dec `json:"delegator_shares"` // total shares issued to a validator's delegators Description Description `json:"description"` // description terms for the validator BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer - Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators - CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge - CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission - CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) + Commission sdk.Dec `json:"commission"` // XXX the commission rate of fees charged to any delegators + CommissionMax sdk.Dec `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge + CommissionChangeRate sdk.Dec `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission + CommissionChangeToday sdk.Dec `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time) // fee related - LastBondedTokens sdk.Rat `json:"prev_bonded_shares"` // last bonded token amount + LastBondedTokens sdk.Dec `json:"prev_bonded_shares"` // last bonded token amount } // get the bech validator from the the regular validator @@ -364,7 +364,7 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator, } // removes tokens from a validator -func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) { +func (v Validator) RemoveTokens(pool Pool, tokens sdk.Dec) (Validator, Pool) { if v.Status == sdk.Bonded { pool = pool.bondedTokensToLoose(tokens) } @@ -376,25 +376,25 @@ func (v Validator) RemoveTokens(pool Pool, tokens sdk.Rat) (Validator, Pool) { //_________________________________________________________________________________________________________ // AddTokensFromDel adds tokens to a validator -func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Rat) { +func (v Validator) AddTokensFromDel(pool Pool, amount int64) (Validator, Pool, sdk.Dec) { // bondedShare/delegatedShare exRate := v.DelegatorShareExRate() - amountRat := sdk.NewRat(amount) + amountDec := sdk.NewDec(amount) if v.Status == sdk.Bonded { - pool = pool.looseTokensToBonded(amountRat) + pool = pool.looseTokensToBonded(amountDec) } - v.Tokens = v.Tokens.Add(amountRat) - issuedShares := amountRat.Quo(exRate) + v.Tokens = v.Tokens.Add(amountDec) + issuedShares := amountDec.Quo(exRate) v.DelegatorShares = v.DelegatorShares.Add(issuedShares) return v, pool, issuedShares } // RemoveDelShares removes delegator shares from a validator. -func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Pool, sdk.Rat) { +func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Dec) (Validator, Pool, sdk.Dec) { issuedTokens := v.DelegatorShareExRate().Mul(delShares) v.Tokens = v.Tokens.Sub(issuedTokens) v.DelegatorShares = v.DelegatorShares.Sub(delShares) @@ -408,19 +408,19 @@ func (v Validator) RemoveDelShares(pool Pool, delShares sdk.Rat) (Validator, Poo // DelegatorShareExRate gets the exchange rate of tokens over delegator shares. // UNITS: tokens/delegator-shares -func (v Validator) DelegatorShareExRate() sdk.Rat { +func (v Validator) DelegatorShareExRate() sdk.Dec { if v.DelegatorShares.IsZero() { - return sdk.OneRat() + return sdk.OneDec() } return v.Tokens.Quo(v.DelegatorShares) } // Get the bonded tokens which the validator holds -func (v Validator) BondedTokens() sdk.Rat { +func (v Validator) BondedTokens() sdk.Dec { if v.Status == sdk.Bonded { return v.Tokens } - return sdk.ZeroRat() + return sdk.ZeroDec() } //______________________________________________________________________ @@ -434,7 +434,7 @@ func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } func (v Validator) GetOwner() sdk.AccAddress { return v.Owner } func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey } -func (v Validator) GetPower() sdk.Rat { return v.BondedTokens() } -func (v Validator) GetTokens() sdk.Rat { return v.Tokens } -func (v Validator) GetDelegatorShares() sdk.Rat { return v.DelegatorShares } +func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } +func (v Validator) GetTokens() sdk.Dec { return v.Tokens } +func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares } func (v Validator) GetBondHeight() int64 { return v.BondHeight } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index f0dff4732..3981f5754 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -75,19 +75,19 @@ func TestRemoveTokens(t *testing.T) { Owner: addr1, PubKey: pk1, Status: sdk.Bonded, - Tokens: sdk.NewRat(100), - DelegatorShares: sdk.NewRat(100), + Tokens: sdk.NewDec(100), + DelegatorShares: sdk.NewDec(100), } pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) pool.BondedTokens = validator.BondedTokens() validator, pool = validator.UpdateStatus(pool, sdk.Bonded) require.Equal(t, sdk.Bonded, validator.Status) // remove tokens and test check everything - validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10)) + validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10)) require.Equal(t, int64(90), validator.Tokens.RoundInt64()) require.Equal(t, int64(90), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(20), pool.LooseTokens.RoundInt64()) @@ -98,7 +98,7 @@ func TestRemoveTokens(t *testing.T) { require.Equal(t, int64(0), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(110), pool.LooseTokens.RoundInt64()) - validator, pool = validator.RemoveTokens(pool, sdk.NewRat(10)) + validator, pool = validator.RemoveTokens(pool, sdk.NewDec(10)) require.Equal(t, int64(80), validator.Tokens.RoundInt64()) require.Equal(t, int64(0), pool.BondedTokens.RoundInt64()) require.Equal(t, int64(110), pool.LooseTokens.RoundInt64()) @@ -106,43 +106,43 @@ func TestRemoveTokens(t *testing.T) { func TestAddTokensValidatorBonded(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Bonded) validator, pool, delShares := validator.AddTokensFromDel(pool, 10) - require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) + require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) - assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.BondedTokens())) + assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) } func TestAddTokensValidatorUnbonding(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Unbonding) validator, pool, delShares := validator.AddTokensFromDel(pool, 10) - require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) + require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) - assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares)) assert.Equal(t, sdk.Unbonding, validator.Status) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) } func TestAddTokensValidatorUnbonded(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(10) + pool.LooseTokens = sdk.NewDec(10) validator := NewValidator(addr1, pk1, Description{}) validator, pool = validator.UpdateStatus(pool, sdk.Unbonded) validator, pool, delShares := validator.AddTokensFromDel(pool, 10) - require.Equal(t, sdk.OneRat(), validator.DelegatorShareExRate()) + require.Equal(t, sdk.OneDec(), validator.DelegatorShareExRate()) - assert.True(sdk.RatEq(t, sdk.NewRat(10), delShares)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), delShares)) assert.Equal(t, sdk.Unbonded, validator.Status) - assert.True(sdk.RatEq(t, sdk.NewRat(10), validator.Tokens)) + assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) } // TODO refactor to make simpler like the AddToken tests above @@ -151,16 +151,16 @@ func TestRemoveDelShares(t *testing.T) { Owner: addr1, PubKey: pk1, Status: sdk.Bonded, - Tokens: sdk.NewRat(100), - DelegatorShares: sdk.NewRat(100), + Tokens: sdk.NewDec(100), + DelegatorShares: sdk.NewDec(100), } poolA := InitialPool() - poolA.LooseTokens = sdk.NewRat(10) + poolA.LooseTokens = sdk.NewDec(10) poolA.BondedTokens = valA.BondedTokens() - require.Equal(t, valA.DelegatorShareExRate(), sdk.OneRat()) + require.Equal(t, valA.DelegatorShareExRate(), sdk.OneDec()) // Remove delegator shares - valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewRat(10)) + valB, poolB, coinsB := valA.RemoveDelShares(poolA, sdk.NewDec(10)) assert.Equal(t, int64(10), coinsB.RoundInt64()) assert.Equal(t, int64(90), valB.DelegatorShares.RoundInt64()) assert.Equal(t, int64(90), valB.BondedTokens().RoundInt64()) @@ -168,13 +168,13 @@ func TestRemoveDelShares(t *testing.T) { assert.Equal(t, int64(20), poolB.LooseTokens.RoundInt64()) // conservation of tokens - require.True(sdk.RatEq(t, + require.True(sdk.DecEq(t, poolB.LooseTokens.Add(poolB.BondedTokens), poolA.LooseTokens.Add(poolA.BondedTokens))) // specific case from random tests - poolTokens := sdk.NewRat(5102) - delShares := sdk.NewRat(115) + poolTokens := sdk.NewDec(5102) + delShares := sdk.NewDec(115) validator := Validator{ Owner: addr1, PubKey: pk1, @@ -183,22 +183,27 @@ func TestRemoveDelShares(t *testing.T) { DelegatorShares: delShares, } pool := Pool{ - BondedTokens: sdk.NewRat(248305), - LooseTokens: sdk.NewRat(232147), + BondedTokens: sdk.NewDec(248305), + LooseTokens: sdk.NewDec(232147), InflationLastTime: time.Unix(0, 0), - Inflation: sdk.NewRat(7, 100), + Inflation: sdk.NewDecWithPrec(7, 2), } - shares := sdk.NewRat(29) + shares := sdk.NewDec(29) _, newPool, tokens := validator.RemoveDelShares(pool, shares) - require.True(sdk.RatEq(t, sdk.NewRat(147958, 115), tokens)) - require.True(sdk.RatEq(t, + + exp, err := sdk.NewDecFromStr("1286.5913043477") + require.NoError(t, err) + + require.True(sdk.DecEq(t, exp, tokens)) + + require.True(sdk.DecEq(t, newPool.LooseTokens.Add(newPool.BondedTokens), pool.LooseTokens.Add(pool.BondedTokens))) } func TestUpdateStatus(t *testing.T) { pool := InitialPool() - pool.LooseTokens = sdk.NewRat(100) + pool.LooseTokens = sdk.NewDec(100) validator := NewValidator(addr1, pk1, Description{}) validator, pool, _ = validator.AddTokensFromDel(pool, 100) @@ -221,8 +226,8 @@ func TestUpdateStatus(t *testing.T) { } func TestPossibleOverflow(t *testing.T) { - poolTokens := sdk.NewRat(2159) - delShares := sdk.NewRat(391432570689183511).Quo(sdk.NewRat(40113011844664)) + poolTokens := sdk.NewDec(2159) + delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664)) validator := Validator{ Owner: addr1, PubKey: pk1, @@ -231,17 +236,17 @@ func TestPossibleOverflow(t *testing.T) { DelegatorShares: delShares, } pool := Pool{ - LooseTokens: sdk.NewRat(100), + LooseTokens: sdk.NewDec(100), BondedTokens: poolTokens, InflationLastTime: time.Unix(0, 0), - Inflation: sdk.NewRat(7, 100), + Inflation: sdk.NewDecWithPrec(7, 2), } tokens := int64(71) msg := fmt.Sprintf("validator %#v", validator) newValidator, _, _ := validator.AddTokensFromDel(pool, tokens) msg = fmt.Sprintf("Added %d tokens to %s", tokens, msg) - require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroRat()), + require.False(t, newValidator.DelegatorShareExRate().LT(sdk.ZeroDec()), "Applying operation \"%s\" resulted in negative DelegatorShareExRate(): %v", msg, newValidator.DelegatorShareExRate()) } From 4b13529f2d40fa17713451cc50756eb8fe53453f Mon Sep 17 00:00:00 2001 From: Dev Ojha <ValarDragon@users.noreply.github.com> Date: Tue, 14 Aug 2018 18:10:57 -0700 Subject: [PATCH 40/97] Merge pull request #2029: fix build error --- client/lcd/lcd_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 9b8c5e439..c5d567e13 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -415,7 +415,7 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) require.Equal(t, validator1Owner, bondedValidators[0].Owner) - require.Equal(t, validator.DelegatorShares.Add(sdk.NewRat(60)).FloatString(), bondedValidators[0].DelegatorShares.FloatString()) + require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String()) bondedValidator := getDelegatorValidator(t, port, addr, validator1Owner) require.Equal(t, validator1Owner, bondedValidator.Owner) From d37de06762e0187ada484efc407575d99f193ac3 Mon Sep 17 00:00:00 2001 From: Dev Ojha <ValarDragon@users.noreply.github.com> Date: Tue, 14 Aug 2018 18:49:40 -0700 Subject: [PATCH 41/97] decimal: Remove unnecessary allocation in bankers round chop (#2030) This is done by making the function mutative. A non-mutative variant is created for functions that depend on it being non-mutative. --- types/decimal.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/types/decimal.go b/types/decimal.go index cd5c048e3..baf2d9573 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -249,7 +249,7 @@ func (d Dec) ToLeftPaddedWithDecimals(totalDigits int8) string { // TODO panic if negative or if totalDigits < len(initStr)??? // evaluate as an integer and return left padded string func (d Dec) ToLeftPadded(totalDigits int8) string { - chopped := chopPrecisionAndRound(d.Int) + chopped := chopPrecisionAndRoundNonMutative(d.Int) intStr := chopped.String() fcode := `%0` + strconv.Itoa(int(totalDigits)) + `s` return fmt.Sprintf(fcode, intStr) @@ -268,9 +268,7 @@ func (d Dec) ToLeftPadded(totalDigits int8) string { // Remove a Precision amount of rightmost digits and perform bankers rounding // on the remainder (gaussian rounding) on the digits which have been removed. // -// TODO We should make this function mutate the input. The functions here -// don't need to allocate different memory for chopped after computing the -// result +// Mutates the input. Use the non-mutative version if that is undesired func chopPrecisionAndRound(d *big.Int) *big.Int { // remove the negative and add it back when returning @@ -283,7 +281,7 @@ func chopPrecisionAndRound(d *big.Int) *big.Int { } // get the trucated quotient and remainder - quo, rem := big.NewInt(0), big.NewInt(0) + quo, rem := d, big.NewInt(0) quo, rem = quo.QuoRem(d, precisionReuse, rem) if rem.Sign() == 0 { // remainder is zero @@ -304,9 +302,14 @@ func chopPrecisionAndRound(d *big.Int) *big.Int { } } +func chopPrecisionAndRoundNonMutative(d *big.Int) *big.Int { + tmp := new(big.Int).Set(d) + return chopPrecisionAndRound(tmp) +} + // RoundInt64 rounds the decimal using bankers rounding func (d Dec) RoundInt64() int64 { - chopped := chopPrecisionAndRound(d.Int) + chopped := chopPrecisionAndRoundNonMutative(d.Int) if !chopped.IsInt64() { panic("Int64() out of bound") } @@ -315,7 +318,7 @@ func (d Dec) RoundInt64() int64 { // RoundInt round the decimal using bankers rounding func (d Dec) RoundInt() Int { - return NewIntFromBigInt(chopPrecisionAndRound(d.Int)) + return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.Int)) } //___________________________________________________________________________________ From a4bcbc972e8e73d661f6cce5179f31a6082fa6ff Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Wed, 15 Aug 2018 19:04:16 +0900 Subject: [PATCH 42/97] Merge PR #2036: Update examples to bech32 Using the addresses in Bech32 form --- examples/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/README.md b/examples/README.md index 33af1b328..d12e3d3fc 100644 --- a/examples/README.md +++ b/examples/README.md @@ -104,9 +104,9 @@ You should now see alice, bob and charlie's account all show up. ``` NAME: ADDRESS: PUBKEY: -alice 90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD 1624DE62201D47E63694448665F5D0217EA8458177728C91C373047A42BD3C0FB78BD0BFA7 -bob 29D721F054537C91F618A0FDBF770DA51EF8C48D 1624DE6220F54B2A2CA9EB4EE30DE23A73D15902E087C09CC5616456DDDD3814769E2E0A16 -charlie 2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E 1624DE6220F8C9FB8B07855FD94126F88A155BD6EB973509AE5595EFDE1AF05B4964836A53 +alice cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f cosmosaccpub1addwnpepq0w037u5g7y7lvdvsred2dehg90j84k0weyss5ynysf0nnnax74agrsxns6 +bob cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz cosmosaccpub1addwnpepqwe97n8lryxrzvamrvjfj24jys3uzf8wndfvqa2l7mh5nsv4jrvdznvyeg6 +charlie cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q cosmosaccpub1addwnpepqdmtxv35rrmv2dvcr3yhfyxj7dzrd4z4rnhmclksq4g55a4wpl54clvx33l ``` @@ -115,15 +115,15 @@ charlie 2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E 1624DE6220F8C9FB8B07855FD94126F Lets send bob and charlie some tokens. First, lets query alice's account so we can see what kind of tokens she has: ``` -basecli account 90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD +basecli account cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f ``` -Where `90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some! +Where `cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f` is alice's address we got from running `basecli keys list`. You should see a large amount of "mycoin" there. If you search for bob's or charlie's address, the command will fail, because they haven't been added into the blockchain database yet since they have no coins. We need to send them some! The following command will send coins from alice, to bob: ``` -basecli send --from=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D +basecli send --from=alice --amount=10000mycoin --to=cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz --sequence=0 --chain-id=test-chain-AE4XQo ``` @@ -136,13 +136,13 @@ Flag Descriptions: Now if we check bobs account, it should have `10000 mycoin`. You can do so by running : ``` -basecli account 29D721F054537C91F618A0FDBF770DA51EF8C48D +basecli account cosmosaccaddr18se8tz6kwwfga6k2yjsu7n64e9z52nen29rhzz ``` Now lets send some from bob to charlie. Make sure you send less than bob has, otherwise the transaction will fail: ``` -basecli send --from=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E +basecli send --from=bob --amount=5000mycoin --to=cosmosaccaddr13wq5mklhn03ljpd4dkph5rflk5a3ssma2ag07q --sequence=0 --chain-id=test-chain-AE4XQo ``` @@ -151,7 +151,7 @@ Note how we use the ``--from`` flag to select a different account to send from. Lets now try to send from bob back to alice: ``` -basecli send --from=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD +basecli send --from=bob --amount=3000mycoin --to=cosmosaccaddr1khygs0qh7gz3p4m39u00mjhvgvc2dcpxhsuh5f --sequence=1 --chain-id=test-chain-AE4XQo ``` From 5fff217e9b5ccdfa665590e4ba6fdf2db1679e95 Mon Sep 17 00:00:00 2001 From: Rigel <rigel.rozanski@gmail.com> Date: Wed, 15 Aug 2018 09:04:01 -0400 Subject: [PATCH 43/97] Merge PR #2033: staking lcd uses owner address not pubkey address --- client/lcd/lcd_test.go | 5 +-- x/stake/client/rest/query.go | 29 +++++++++--- x/stake/client/rest/utils.go | 86 +++++++++--------------------------- 3 files changed, 44 insertions(+), 76 deletions(-) diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index c5d567e13..db584834a 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -376,11 +376,8 @@ func TestValidatorQuery(t *testing.T) { require.Equal(t, 1, len(pks)) validator1Owner := sdk.AccAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Owner) - bech32ValAddress, err := sdk.Bech32ifyValPub(pks[0]) - require.NoError(t, err) - assert.Equal(t, validator.PubKey, bech32ValAddress, "The returned validator does not hold the correct data") + assert.Equal(t, validator.Owner, validator1Owner, "The returned validator does not hold the correct data") } func TestBonding(t *testing.T) { diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index b7d2b10a4..4dfaa0f7f 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -507,25 +507,40 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler valAddress, err := sdk.AccAddressFromBech32(bech32validatorAddr) if err != nil { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Error: %s", err.Error()))) + w.Write([]byte(fmt.Sprintf("error: %s", err.Error()))) return } - kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName) + key := stake.GetValidatorKey(valAddress) + + res, err := cliCtx.QueryStore(key, storeName) if err != nil { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("Error: %s", err.Error()))) + w.Write([]byte(fmt.Sprintf("couldn't query validator, error: %s", err.Error()))) return } - validator, err := getValidator(valAddress, kvs, cdc) + // the query will return empty if there is no data for this record + if len(res) == 0 { + w.WriteHeader(http.StatusNoContent) + return + } + + validator, err := types.UnmarshalValidator(cdc, valAddress, res) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprintf("couldn't query validator. Error: %s", err.Error()))) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) return } - output, err = cdc.MarshalJSON(validator) + bech32Validator, err := validator.Bech32Validator() + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + output, err = cdc.MarshalJSON(bech32Validator) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Error: %s", err.Error()))) diff --git a/x/stake/client/rest/utils.go b/x/stake/client/rest/utils.go index 1a0809089..96588f73b 100644 --- a/x/stake/client/rest/utils.go +++ b/x/stake/client/rest/utils.go @@ -1,7 +1,6 @@ package rest import ( - "bytes" "fmt" "net/http" @@ -12,7 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" "github.com/cosmos/cosmos-sdk/x/stake/tags" "github.com/cosmos/cosmos-sdk/x/stake/types" - "github.com/pkg/errors" rpcclient "github.com/tendermint/tendermint/rpc/client" ) @@ -26,33 +24,36 @@ func contains(stringSlice []string, txType string) bool { return false } -func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAccAddr sdk.AccAddress) ( - validator types.BechValidator, httpStatusCode int, errMsg string, err error) { +func getDelegatorValidator(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( + bech32Validator types.BechValidator, httpStatusCode int, errMsg string, err error) { - keyDel := stake.GetDelegationKey(delegatorAddr, validatorAccAddr) - - res, err := cliCtx.QueryStore(keyDel, storeName) + key := stake.GetDelegationKey(delegatorAddr, validatorAddr) + res, err := cliCtx.QueryStore(key, storeName) if err != nil { return types.BechValidator{}, http.StatusInternalServerError, "couldn't query delegation. Error: ", err } - if len(res) == 0 { return types.BechValidator{}, http.StatusNoContent, "", nil } - kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName) + key = stake.GetValidatorKey(validatorAddr) + res, err = cliCtx.QueryStore(key, storeName) if err != nil { - return types.BechValidator{}, http.StatusInternalServerError, "Error: ", err + return types.BechValidator{}, http.StatusInternalServerError, "couldn't query validator. Error: ", err } - if len(kvs) == 0 { + if len(res) == 0 { return types.BechValidator{}, http.StatusNoContent, "", nil } - - validator, errVal := getValidatorFromAccAdrr(validatorAccAddr, kvs, cdc) - if errVal != nil { - return types.BechValidator{}, http.StatusInternalServerError, "Couldn't get info from validator. Error: ", errVal + validator, err := types.UnmarshalValidator(cdc, validatorAddr, res) + if err != nil { + return types.BechValidator{}, http.StatusBadRequest, "", err } - return validator, http.StatusOK, "", nil + bech32Validator, err = validator.Bech32Validator() + if err != nil { + return types.BechValidator{}, http.StatusBadRequest, "", err + } + + return bech32Validator, http.StatusOK, "", nil } func getDelegatorDelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( @@ -104,8 +105,8 @@ func getDelegatorUndelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, delegatorAddr sdk.AccAddress, validatorAddr sdk.AccAddress) ( regelegations types.Redelegation, httpStatusCode int, errMsg string, err error) { - keyRedelegateTo := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr) - marshalledRedelegations, err := cliCtx.QueryStore(keyRedelegateTo, storeName) + key := stake.GetREDsByDelToValDstIndexKey(delegatorAddr, validatorAddr) + marshalledRedelegations, err := cliCtx.QueryStore(key, storeName) if err != nil { return types.Redelegation{}, http.StatusInternalServerError, "couldn't query redelegation. Error: ", err } @@ -114,7 +115,7 @@ func getDelegatorRedelegations(cliCtx context.CLIContext, cdc *wire.Codec, deleg return types.Redelegation{}, http.StatusNoContent, "", nil } - redelegations, err := types.UnmarshalRED(cdc, keyRedelegateTo, marshalledRedelegations) + redelegations, err := types.UnmarshalRED(cdc, key, marshalledRedelegations) if err != nil { return types.Redelegation{}, http.StatusInternalServerError, "couldn't unmarshall redelegations. Error: ", err } @@ -156,55 +157,10 @@ func getValidators(validatorKVs []sdk.KVPair, cdc *wire.Codec) ([]types.BechVali return validators, nil } -// gets a validator given a ValAddress -func getValidator(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) { - // parse out the validators - for _, kv := range validatorKVs { - addr := kv.Key[1:] - validator, err := types.UnmarshalValidator(cdc, addr, kv.Value) - if err != nil { - return stake.BechValidator{}, err - } - - ownerAddress := validator.PubKey.Address() - if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) { - bech32Validator, err := validator.Bech32Validator() - if err != nil { - return stake.BechValidator{}, err - } - - return bech32Validator, nil - } - } - return stake.BechValidator{}, errors.Errorf("Couldn't find validator") -} - -// gets a validator given an AccAddress -func getValidatorFromAccAdrr(address sdk.AccAddress, validatorKVs []sdk.KVPair, cdc *wire.Codec) (stake.BechValidator, error) { - // parse out the validators - for _, kv := range validatorKVs { - addr := kv.Key[1:] - validator, err := types.UnmarshalValidator(cdc, addr, kv.Value) - if err != nil { - return stake.BechValidator{}, err - } - - ownerAddress := validator.PubKey.Address() - if bytes.Equal(ownerAddress.Bytes(), address.Bytes()) { - bech32Validator, err := validator.Bech32Validator() - if err != nil { - return stake.BechValidator{}, err - } - - return bech32Validator, nil - } - } - return stake.BechValidator{}, errors.Errorf("Couldn't find validator") -} - // gets all Bech32 validators from a key func getBech32Validators(storeName string, cliCtx context.CLIContext, cdc *wire.Codec) ( validators []types.BechValidator, httpStatusCode int, errMsg string, err error) { + // Get all validators using key kvs, err := cliCtx.QuerySubspace(stake.ValidatorsKey, storeName) if err != nil { From c9358ec198070dc8fb8d0e2f48f6b8b6a781c848 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 15 Aug 2018 16:59:46 +0200 Subject: [PATCH 44/97] R4R: Fix repeated cmds in CLI for staking (v.0.24.0 release) (#2043) * Cherry picked commits * Update CHANGELOG.md --- CHANGELOG.md | 28 +++++++++++++++------------- cmd/gaia/cmd/gaiacli/main.go | 4 ++++ x/stake/client/cli/query.go | 12 ++++++------ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b6103526..930de1332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,8 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) - [x/stake] change `--keybase-sig` to `--identity` - [x/stake] \#1828 Force user to specify amount on create-validator command by removing default - - [x/gov] Change `--proposalID` to `--proposal-id` - - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` + - [x/gov] Change `--proposalID` to `--proposal-id` + - [x/stake, x/gov] \#1606 Use `--from` instead of adhoc flags like `--address-validator` and `--proposer` to indicate the sender address. - \#1551 Remove `--name` completely - Genesis/key creation (`gaiad init`) now supports user-provided key passwords @@ -26,12 +26,12 @@ BREAKING CHANGES - [x/stake] Inflation doesn't use rationals in calculation (performance boost) - [x/stake] Persist a map from `addr->pubkey` in the state since BeginBlock doesn't provide pubkeys. - - [x/gov] \#1781 Added tags sub-package, changed tags to use dash-case + - [x/gov] \#1781 Added tags sub-package, changed tags to use dash-case - [x/gov] \#1688 Governance parameters are now stored in globalparams store - [x/gov] \#1859 Slash validators who do not vote on a proposal - [x/gov] \#1914 added TallyResult type that gets stored in Proposal after tallying is finished - -* SDK + +* SDK - [baseapp] Msgs are no longer run on CheckTx, removed `ctx.IsCheckTx()` - [baseapp] NewBaseApp constructor takes sdk.TxDecoder as argument instead of wire.Codec - [types] sdk.NewCoin takes sdk.Int, sdk.NewInt64Coin takes int64 @@ -40,14 +40,14 @@ BREAKING CHANGES - Removed all tx related fields and logic (building & signing) to separate structure `TxContext` in `x/auth/client/context` -* Tendermint +* Tendermint - v0.22.5 -> See [Tendermint PR](https://github.com/tendermint/tendermint/pull/1966) - - change all the cryptography imports. + - change all the cryptography imports. - v0.23.0 -> See [Changelog](https://github.com/tendermint/tendermint/blob/v0.23.0/CHANGELOG.md#0230) and [SDK PR](https://github.com/cosmos/cosmos-sdk/pull/1927) - BeginBlock no longer includes crypto.Pubkey - - use time.Time instead of int64 for time. + - use time.Time instead of int64 for time. FEATURES @@ -56,11 +56,12 @@ FEATURES * Gaia CLI (`gaiacli`) - [x/gov] added `query-proposals` command. Can filter by `depositer`, `voter`, and `status` + - [x/stake] \#2043 Added staking query cli cmds for unbonding-delegations and redelegations * Gaia - [networks] Added ansible scripts to upgrade seed nodes on a network -* SDK +* SDK - [x/mock/simulation] Randomized simulation framework - Modules specify invariants and operations, preferably in an x/[module]/simulation package - Modules can test random combinations of their own operations @@ -78,10 +79,10 @@ IMPROVEMENTS - [spec] \#967 Inflation and distribution specs drastically improved - [x/gov] \#1773 Votes on a proposal can now be queried - [x/gov] Initial governance parameters can now be set in the genesis file - - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. + - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. - [config] \#1930 Transactions indexer indexes all tags by default. -* SDK +* SDK - [baseapp] \#1587 Allow any alphanumeric character in route - [baseapp] Allow any alphanumeric character in route - [tools] Remove `rm -rf vendor/` from `make get_vendor_deps` @@ -95,13 +96,14 @@ BUG FIXES * Gaia CLI (`gaiacli`) - \#1766 Fixes bad example for keybase identity + - [x/stake] \#2021 Fixed repeated CLI commands in staking * Gaia - \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates - \#1799 Fix `gaiad export` - \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators - [x/stake] \#1858 Fixed bug where the cliff validator was not updated correctly - - [tests] \#1675 Fix non-deterministic `test_cover` + - [tests] \#1675 Fix non-deterministic `test_cover` - [tests] \#1551 Fixed invalid LCD test JSON payload in `doIBCTransfer` - [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) - [x/gov] \#1757 Fix VoteOption conversion to String @@ -274,7 +276,7 @@ FEATURES * [types] Added MinInt and MinUint functions * [gaiad] `unsafe_reset_all` now resets addrbook.json * [democoin] add x/oracle, x/assoc -* [tests] created a randomized testing framework. +* [tests] created a randomized testing framework. - Currently bank has limited functionality in the framework - Auth has its invariants checked within the framework * [tests] Add WaitForNextNBlocksTM helper method diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 9c4d67b8c..02a96b614 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -88,6 +88,10 @@ func main() { stakecmd.GetCmdQueryValidators("stake", cdc), stakecmd.GetCmdQueryDelegation("stake", cdc), stakecmd.GetCmdQueryDelegations("stake", cdc), + stakecmd.GetCmdQueryUnbondingDelegation("stake", cdc), + stakecmd.GetCmdQueryUnbondingDelegations("stake", cdc), + stakecmd.GetCmdQueryRedelegation("stake", cdc), + stakecmd.GetCmdQueryRedelegations("stake", cdc), slashingcmd.GetCmdQuerySigningInfo("slashing", cdc), )...) stakeCmd.AddCommand( diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 5ac303f9f..015d6ffcf 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -312,11 +312,11 @@ func GetCmdQueryUnbondingDelegations(storeName string, cdc *wire.Codec) *cobra.C } // GetCmdQueryRedelegation implements the command to query a single -// unbonding-delegation record. +// redelegation record. func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "unbonding-delegation", - Short: "Query an unbonding-delegation record based on delegator and validator address", + Use: "redelegation", + Short: "Query a redelegation record based on delegator and a source and destination validator address", RunE: func(cmd *cobra.Command, args []string) error { valSrcAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressValidatorSrc)) if err != nil { @@ -373,11 +373,11 @@ func GetCmdQueryRedelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // GetCmdQueryRedelegations implements the command to query all the -// unbonding-delegation records for a delegator. +// redelegation records for a delegator. func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ - Use: "unbonding-delegations [delegator-addr]", - Short: "Query all unbonding-delegations records for one delegator", + Use: "redelegations [delegator-addr]", + Short: "Query all redelegations records for one delegator", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { delegatorAddr, err := sdk.AccAddressFromBech32(args[0]) From 97ea51a3357da5041948312b1149f62672af5df9 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Wed, 15 Aug 2018 14:51:19 -0400 Subject: [PATCH 45/97] Merge pull request #2023: Terminate Update Bonded Validators Iteration Properly --- Gopkg.lock | 23 +++++++------- PENDING.md | 1 + x/stake/keeper/validator.go | 60 ++++++++++++++++++++----------------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 6e45f42b0..de244c162 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -38,7 +38,7 @@ name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" + revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -340,19 +341,19 @@ [[projects]] branch = "master" - digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] pruneopts = "UT" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] - digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" [[projects]] digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" @@ -517,7 +518,7 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "f027049dab0ad238e394a753dba2d14753473a04" + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" @@ -537,14 +538,14 @@ [[projects]] branch = "master" - digest = "1:4d64ef38a30b73db6e8e7a2824b7fd356d921e0ee3fdd3248658996821d3b47d" + digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + revision = "4e1fef5609515ec7a2cee7b5de30ba6d9b438cbf" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -575,7 +576,7 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" diff --git a/PENDING.md b/PENDING.md index 4fcc0c6a9..8cf301a01 100644 --- a/PENDING.md +++ b/PENDING.md @@ -75,6 +75,7 @@ IMPROVEMENTS * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [server] \#1930 Transactions indexer indexes all tags by default. * [x/stake] \#2000 Added tests for new staking endpoints +* [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. BUG FIXES diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index eaaf3df9e..ce5a19061 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -417,20 +417,24 @@ func (k Keeper) UpdateBondedValidators( } } - // increment bondedValidatorsCount / get the validator to bond - if !validator.Revoked { - if validator.Status != sdk.Bonded { - validatorToBond = validator - newValidatorBonded = true + if validator.Revoked { + // we should no longer consider jailed validators as they are ranked + // lower than any non-jailed/bonded validators + if validator.Status == sdk.Bonded { + panic(fmt.Sprintf("revoked validator cannot be bonded for address: %s\n", ownerAddr)) } - bondedValidatorsCount++ - - // sanity check - } else if validator.Status == sdk.Bonded { - panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr)) + break } + // increment the total number of bonded validators and potentially mark + // the validator to bond + if validator.Status != sdk.Bonded { + validatorToBond = validator + newValidatorBonded = true + } + + bondedValidatorsCount++ iterator.Next() } @@ -468,7 +472,6 @@ func (k Keeper) UpdateBondedValidators( // full update of the bonded validator set, many can be added/kicked func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { - store := ctx.KVStore(k.storeKey) // clear the current validators store, add to the ToKickOut temp store @@ -476,27 +479,26 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) for ; iterator.Valid(); iterator.Next() { ownerAddr := GetAddressFromValBondedIndexKey(iterator.Key()) - toKickOut[string(ownerAddr)] = 0 // set anything + toKickOut[string(ownerAddr)] = 0 } + iterator.Close() + var validator types.Validator + oldCliffValidatorAddr := k.GetCliffValidator(ctx) maxValidators := k.GetParams(ctx).MaxValidators bondedValidatorsCount := 0 - iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) // largest to smallest - var validator types.Validator + iterator = sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) for { if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) { break } - // either retrieve the original validator from the store, - // or under the situation that this is the "new validator" just - // use the validator provided because it has not yet been updated - // in the main validator store - ownerAddr := iterator.Value() var found bool + + ownerAddr := iterator.Value() validator, found = k.GetValidator(ctx, ownerAddr) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", ownerAddr)) @@ -506,23 +508,26 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { if found { delete(toKickOut, string(ownerAddr)) } else { - - // if it wasn't in the toKickOut group it means - // this wasn't a previously a validator, therefor - // update the validator to enter the validator group + // If the validator wasn't in the toKickOut group it means it wasn't + // previously a validator, therefor update the validator to enter + // the validator group. validator = k.bondValidator(ctx, validator) } - if !validator.Revoked { - bondedValidatorsCount++ - } else { + if validator.Revoked { + // we should no longer consider jailed validators as they are ranked + // lower than any non-jailed/bonded validators if validator.Status == sdk.Bonded { - panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr)) + panic(fmt.Sprintf("revoked validator cannot be bonded for address: %s\n", ownerAddr)) } + + break } + bondedValidatorsCount++ iterator.Next() } + iterator.Close() // clear or set the cliff validator @@ -532,7 +537,6 @@ func (k Keeper) UpdateBondedValidatorsFull(ctx sdk.Context) { k.clearCliffValidator(ctx) } - // perform the actual kicks kickOutValidators(k, ctx, toKickOut) return } From 629c18541da53de2408d065fa21e19af03559e24 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Wed, 15 Aug 2018 15:12:04 -0400 Subject: [PATCH 46/97] Update ICS number to 030 --- docs/ics/ics-xxx-signed-messages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-xxx-signed-messages.md index 6eeee1671..1e5b7c41a 100644 --- a/docs/ics/ics-xxx-signed-messages.md +++ b/docs/ics/ics-xxx-signed-messages.md @@ -1,4 +1,4 @@ -# ICS XXX: Cosmos Signed Messages +# ICS 030: Cosmos Signed Messages >TODO: Replace with valid ICS number and possibly move to new location. From a9f240035c339ae2352c3e9e74e2e7a31e0efa3b Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Wed, 15 Aug 2018 15:13:51 -0400 Subject: [PATCH 47/97] Rename ics-xxx-signed-messages.md to ics-030-signed-messages.md --- .../{ics-xxx-signed-messages.md => ics-030-signed-messages.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/ics/{ics-xxx-signed-messages.md => ics-030-signed-messages.md} (100%) diff --git a/docs/ics/ics-xxx-signed-messages.md b/docs/ics/ics-030-signed-messages.md similarity index 100% rename from docs/ics/ics-xxx-signed-messages.md rename to docs/ics/ics-030-signed-messages.md From 4fbaee205f4802e929ad3b24b3520332209b15f7 Mon Sep 17 00:00:00 2001 From: Alessio Treglia <quadrispro@ubuntu.com> Date: Wed, 15 Aug 2018 21:49:06 +0200 Subject: [PATCH 48/97] Merge pull request #1997: Handle unmarshalling failures gracefully in x/stake commands * Handle panic gracefully when unbond begin fails See #1831 * Handle failure to query delegation gracefully. Closes #1907 * Update PENDING.md * Reuse stake's error functions * New ErrBadValidatorAddr error UnmarshalValidator() checks the address length first; it does not make sense to attempt unmarshalling if the address is wrong. * New ErrBadDelegationAddr error * Introduce ErrBad{Redelegation,UnbondingDelegation}Addr custom errors to replace errors.New() calls * Replace ErrBadUnbondingDelegationAddr with ErrBadDelegationAddr to avoid duplication Thanks: @melekes for pointing this out * Use sdk.AddrLen instead of hardcoded address length * s/triple/tuple/ ## mention PR id in PENDING.md --- PENDING.md | 1 + x/stake/client/cli/query.go | 5 ++++- x/stake/client/cli/tx.go | 7 ++++--- x/stake/types/delegation.go | 8 ++++---- x/stake/types/errors.go | 13 +++++++++++++ x/stake/types/validator.go | 10 ++++------ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/PENDING.md b/PENDING.md index 8cf301a01..fc3c674f4 100644 --- a/PENDING.md +++ b/PENDING.md @@ -101,3 +101,4 @@ BUG FIXES * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) +* [cli] \#1997 Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index 5ac303f9f..dc2c8e30d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -139,7 +139,10 @@ func GetCmdQueryDelegation(storeName string, cdc *wire.Codec) *cobra.Command { } // parse out the delegation - delegation := types.MustUnmarshalDelegation(cdc, key, res) + delegation, err := types.UnmarshalDelegation(cdc, key, res) + if err != nil { + return err + } switch viper.Get(cli.OutputFlag) { case "text": diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index bf2df4913..5c1eec834 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -273,11 +273,12 @@ func getShares( if err != nil { return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err) } - - delegation := types.MustUnmarshalDelegation(cdc, key, resQuery) + delegation, err := types.UnmarshalDelegation(cdc, key, resQuery) + if err != nil { + return sdk.ZeroRat(), err + } sharesAmount = sharesPercent.Mul(delegation.Shares) } - return } diff --git a/x/stake/types/delegation.go b/x/stake/types/delegation.go index 78111c030..e3227c3ed 100644 --- a/x/stake/types/delegation.go +++ b/x/stake/types/delegation.go @@ -2,7 +2,6 @@ package types import ( "bytes" - "errors" "fmt" "time" @@ -48,12 +47,13 @@ func UnmarshalDelegation(cdc *wire.Codec, key, value []byte) (delegation Delegat var storeValue delegationValue err = cdc.UnmarshalBinary(value, &storeValue) if err != nil { + err = fmt.Errorf("%v: %v", ErrNoDelegation(DefaultCodespace).Data(), err) return } addrs := key[1:] // remove prefix bytes if len(addrs) != 2*sdk.AddrLen { - err = errors.New("unexpected key length") + err = fmt.Errorf("%v", ErrBadDelegationAddr(DefaultCodespace).Data()) return } delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) @@ -143,7 +143,7 @@ func UnmarshalUBD(cdc *wire.Codec, key, value []byte) (ubd UnbondingDelegation, addrs := key[1:] // remove prefix bytes if len(addrs) != 2*sdk.AddrLen { - err = errors.New("unexpected key length") + err = fmt.Errorf("%v", ErrBadDelegationAddr(DefaultCodespace).Data()) return } delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) @@ -235,7 +235,7 @@ func UnmarshalRED(cdc *wire.Codec, key, value []byte) (red Redelegation, err err addrs := key[1:] // remove prefix bytes if len(addrs) != 3*sdk.AddrLen { - err = errors.New("unexpected key length") + err = fmt.Errorf("%v", ErrBadRedelegationAddr(DefaultCodespace).Data()) return } delAddr := sdk.AccAddress(addrs[:sdk.AddrLen]) diff --git a/x/stake/types/errors.go b/x/stake/types/errors.go index 1595a70d9..d44ed411c 100644 --- a/x/stake/types/errors.go +++ b/x/stake/types/errors.go @@ -17,6 +17,7 @@ const ( CodeInvalidDelegation CodeType = 102 CodeInvalidInput CodeType = 103 CodeValidatorJailed CodeType = 104 + CodeInvalidAddress CodeType = sdk.CodeInvalidAddress CodeUnauthorized CodeType = sdk.CodeUnauthorized CodeInternal CodeType = sdk.CodeInternal CodeUnknownRequest CodeType = sdk.CodeUnknownRequest @@ -27,6 +28,10 @@ func ErrNilValidatorAddr(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidInput, "validator address is nil") } +func ErrBadValidatorAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidAddress, "validator address is invalid") +} + func ErrNoValidatorFound(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidValidator, "validator does not exist for that address") } @@ -68,6 +73,10 @@ func ErrBadDenom(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "invalid coin denomination") } +func ErrBadDelegationAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, validator) pair") +} + func ErrBadDelegationAmount(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "amount must be > 0") } @@ -118,6 +127,10 @@ func ErrExistingUnbondingDelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "existing unbonding delegation found") } +func ErrBadRedelegationAddr(codespace sdk.CodespaceType) sdk.Error { + return sdk.NewError(codespace, CodeInvalidInput, "unexpected address length for this (address, srcValidator, dstValidator) tuple") +} + func ErrNoRedelegation(codespace sdk.CodespaceType) sdk.Error { return sdk.NewError(codespace, CodeInvalidDelegation, "no redelegation found") } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index c9626b5ec..bd7d76993 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -2,7 +2,6 @@ package types import ( "bytes" - "errors" "fmt" abci "github.com/tendermint/tendermint/abci/types" @@ -115,17 +114,16 @@ func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator // unmarshal a redelegation from a store key and value func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Validator, err error) { + if len(ownerAddr) != sdk.AddrLen { + err = fmt.Errorf("%v", ErrBadValidatorAddr(DefaultCodespace).Data()) + return + } var storeValue validatorValue err = cdc.UnmarshalBinary(value, &storeValue) if err != nil { return } - if len(ownerAddr) != 20 { - err = errors.New("unexpected address length") - return - } - return Validator{ Owner: ownerAddr, PubKey: storeValue.PubKey, From 599b8ba4cf26d139b827aac504092ffb77e66080 Mon Sep 17 00:00:00 2001 From: Aditya Sripal <adityasripal@gmail.com> Date: Wed, 15 Aug 2018 13:54:03 -0700 Subject: [PATCH 49/97] Fix bug, clearer logic --- docs/spec/auth/vesting.md | 71 +++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index a69a342e4..344e10049 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -20,11 +20,9 @@ NOTE: `Now = ctx.BlockHeader().Time` type VestingAccount interface { Account AssertIsVestingAccount() // existence implies that account is vesting. - ConvertAccount(sdk.Context) BaseAccount - // Calculates total amount of unlocked coins released by vesting schedule - // May be larger than total coins in account right now - TotalUnlockedCoins(sdk.Context) sdk.Coins + // Calculates amount of coins that can be sent to other accounts given the current time + SendableCoins(sdk.Context) sdk.Coins } // Implements Vesting Account @@ -33,22 +31,24 @@ type ContinuousVestingAccount struct { BaseAccount OriginalCoins sdk.Coins // Coins in account on Initialization ReceivedCoins sdk.Coins // Coins received from other accounts + SentCoins sdk.Coins // Coins sent to other accounts // StartTime and EndTime used to calculate how much of OriginalCoins is unlocked at any given point - StartTime int64 - EndTime int64 + StartTime time.Time + EndTime time.Time } -// ConvertAccount converts VestingAccount into BaseAccount -// Will convert only after account has fully vested -ConvertAccount(vacc ContinuousVestingAccount, ctx sdk.Context) (BaseAccount): - if Now > vacc.EndTime: - return vacc.BaseAccount - // Uses time in context to calculate total unlocked coins -TotalUnlockedCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins: - unlockedCoins := ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) - return unlockedCoins +SendableCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins: + + // Coins unlocked by vesting schedule + unlockedCoins := ReceivedCoins - SentCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) + + // Must still check for currentCoins constraint since some unlocked coins may have been delegated. + currentCoins := vacc.BaseAccount.GetCoins() + + // min will return sdk.Coins with each denom having the minimum amount from unlockedCoins and currentCoins + return min(unlockedCoins, currentCoins) ``` @@ -58,13 +58,13 @@ The `VestingAccount` interface is used to assert that an account is a vesting ac vacc, ok := acc.(VestingAccount); ok ``` -as well as to convert to BaseAccount again once the account has fully vested. +as well as to calculate the SendableCoins at any given moment. The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalCoins`, `ReceivedCoins`, -`StartTime`, and `EndTime` to calculate how many coins are sendable at any given point. Once the account has fully vested, -the next `bank.MsgSend` will convert the account into a `BaseAccount` and store it in state as such from that point on. -Since the vesting restrictions need to be implemented on a per-module basis, the `ContinuouosVestingAccount` implements -the `Account` interface exactly like `BaseAccount`. +`SentCoins`, `StartTime`, and `EndTime` to calculate how many coins are sendable at any given point. +Since the vesting restrictions need to be implemented on a per-module basis, the `ContinuousVestingAccount` implements +the `Account` interface exactly like `BaseAccount`. Thus, `ContinuousVestingAccount.GetCoins()` will return the total of +both locked coins and unlocked coins currently in the account. ##### Changes to Keepers/Handler @@ -73,19 +73,15 @@ handled at the `bank.Keeper` level. Specifically in methods that are explicitly `sendCoins` and `inputOutputCoins`. These methods must check that an account is a vesting account using the check described above. ```go -if Now < vestingAccount.EndTime: - // NOTE: SendableCoins may be greater than total coins in account - // because coins can be subtracted by staking module - // SendableCoins denotes maximum coins allowed to be spent. - if msg.Amount > vestingAccount.TotalUnlockedCoins() then fail +if acc is VestingAccount and Now < vestingAccount.EndTime: + // Check if amount is less than currently allowed sendable coins + if msg.Amount > vestingAccount.SendableCoins(ctx) then fail + else: + vestingAccount.SentCoins += msg.Amount -// Account fully vested, convert to BaseAccount else: - account = ConvertAccount(account) - -// Must still check if account has enough coins, -// since SendableCoins does not check this. -if msg.Amount > account.GetCoins() then fail + // Account has fully vested, treat like regular account + if msg.Amount > account.GetCoins() then fail // All checks passed, send the coins SendCoins(inputs, outputs) @@ -95,9 +91,10 @@ SendCoins(inputs, outputs) Coins that are sent to a vesting account after initialization by users sending them coins should be spendable immediately after receiving them. Thus, handlers (like staking or bank) that send coins that a vesting account did not originally own should increment `ReceivedCoins` by the amount sent. +Unlocked coins that are sent to other accounts will increment the vesting account's `SentCoins` attribute. CONTRACT: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account unbonds from a validator, their tokens should be added back to account but `ReceivedCoins` SHOULD NOT be incremented. -However when the staking handler is handing out fees or inflation rewards, then `ReceivedCoins` SHOULD be incremented. +However when the staking handler is handing out fees/inflation rewards or a user sends coins to vesting account, then `ReceivedCoins` SHOULD be incremented. ### Initializing at Genesis @@ -135,7 +132,7 @@ initChainer: `OriginalCoins`: Amount of coins in account at Genesis -`CurrentCoins`: Coins currently in the baseaccount (both locked and unlocked) +`CurrentCoins`: Coins currently in the baseaccount (both locked and unlocked: `vestingAccount.GetCoins`) `ReceivedCoins`: Coins received from other accounts (always unlocked) @@ -147,16 +144,16 @@ initChainer: Maximum amount of coins vesting schedule allows to be sent: -`ReceivedCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime)` +`ReceivedCoins - SentCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime)` -`ReceivedCoins + OriginalCoins - LockedCoins` +`ReceivedCoins - SentCoins + OriginalCoins - LockedCoins` Coins currently in Account: `CurrentCoins = OriginalCoins + ReceivedCoins - Delegated - Sent` -`CurrentCoins = vestingAccount.BaseAccount.GetCoins()` +`CurrentCoins = vestingAccount.GetCoins()` **Maximum amount of coins spendable right now:** -`min( ReceivedCoins + OriginalCoins - LockedCoins, CurrentCoins )` +`min( ReceivedCoins - SentCoins + OriginalCoins - LockedCoins, CurrentCoins )` From 422dfa3de958eb8a009efb8a7940e140cc33f912 Mon Sep 17 00:00:00 2001 From: Rigel <rigel.rozanski@gmail.com> Date: Wed, 15 Aug 2018 18:35:17 -0400 Subject: [PATCH 50/97] Merge pr #2051: smol compile bug --- x/stake/client/cli/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/stake/client/cli/tx.go b/x/stake/client/cli/tx.go index 5c1eec834..9f04f2ed2 100644 --- a/x/stake/client/cli/tx.go +++ b/x/stake/client/cli/tx.go @@ -275,7 +275,7 @@ func getShares( } delegation, err := types.UnmarshalDelegation(cdc, key, resQuery) if err != nil { - return sdk.ZeroRat(), err + return sdk.ZeroDec(), err } sharesAmount = sharesPercent.Mul(delegation.Shares) } From 7b5ca5adbdbda0123d389d0866fa9ee415aefe8d Mon Sep 17 00:00:00 2001 From: Zach <zach.ramsay@gmail.com> Date: Thu, 16 Aug 2018 04:16:41 -0700 Subject: [PATCH 51/97] duplicate/old CODEOWNERS (#2055) --- CODEOWNERS | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index 2992bcf66..000000000 --- a/CODEOWNERS +++ /dev/null @@ -1,2 +0,0 @@ -* @jaekwon -* @ebuchman From 3d50567034ffc740070022f25ab59bbc65c055f1 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Thu, 16 Aug 2018 17:36:15 +0200 Subject: [PATCH 52/97] Merge PR #1783: Slashing, validator set, and governance simulation --- .circleci/config.yml | 30 +++- CHANGELOG.md | 3 + Gopkg.lock | 51 +++--- Makefile | 22 +-- baseapp/baseapp.go | 2 +- cmd/gaia/app/sim_test.go | 102 ++++++++++-- tests/test_cover.sh | 2 +- types/stake.go | 5 +- x/bank/simulation/msgs.go | 4 + x/bank/simulation/sim_test.go | 6 +- x/gov/handler.go | 11 ++ x/gov/keeper.go | 12 ++ x/gov/simulation/invariants.go | 19 +++ x/gov/simulation/msgs.go | 132 +++++++++++++++ x/gov/simulation/sim_test.go | 68 ++++++++ x/mock/app.go | 28 +++- x/mock/simulation/constants.go | 31 ++++ x/mock/simulation/random_simulate_blocks.go | 172 ++++++++++++++++++-- x/mock/simulation/transition_matrix.go | 70 ++++++++ x/mock/simulation/types.go | 6 + x/mock/simulation/util.go | 14 +- x/slashing/simulation/invariants.go | 18 ++ x/slashing/simulation/msgs.go | 34 ++++ x/stake/genesis.go | 1 - x/stake/keeper/validator.go | 9 +- x/stake/simulation/msgs.go | 5 +- x/stake/simulation/sim_test.go | 8 +- x/stake/types/validator.go | 10 +- 28 files changed, 784 insertions(+), 91 deletions(-) create mode 100644 x/gov/simulation/invariants.go create mode 100644 x/gov/simulation/msgs.go create mode 100644 x/gov/simulation/sim_test.go create mode 100644 x/mock/simulation/constants.go create mode 100644 x/mock/simulation/transition_matrix.go create mode 100644 x/slashing/simulation/invariants.go create mode 100644 x/slashing/simulation/msgs.go diff --git a/.circleci/config.yml b/.circleci/config.yml index bf7892a8c..b778653ea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,7 +85,7 @@ jobs: export PATH="$GOBIN:$PATH" make test_cli - test_sim: + test_sim_modules: <<: *defaults parallelism: 1 steps: @@ -96,11 +96,26 @@ jobs: - restore_cache: key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} - run: - name: Test simulation + name: Test individual module simulations command: | export PATH="$GOBIN:$PATH" - export GAIA_SIMULATION_SEED=1531897442166404087 - make test_sim + make test_sim_modules + + test_sim_gaia_fast: + <<: *defaults + parallelism: 1 + steps: + - attach_workspace: + at: /tmp/workspace + - restore_cache: + key: v1-pkg-cache + - restore_cache: + key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - run: + name: Test full Gaia simulation + command: | + export PATH="$GOBIN:$PATH" + make test_sim_gaia_fast test_cover: <<: *defaults @@ -118,7 +133,7 @@ jobs: command: | export PATH="$GOBIN:$PATH" make install - for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do + for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation' | circleci tests split --split-by=timings); do id=$(basename "$pkg") GOCACHE=off go test -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" done @@ -161,7 +176,10 @@ workflows: - test_cli: requires: - setup_dependencies - - test_sim: + - test_sim_modules: + requires: + - setup_dependencies + - test_sim_gaia_fast: requires: - setup_dependencies - test_cover: diff --git a/CHANGELOG.md b/CHANGELOG.md index 930de1332..b4de50494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,9 @@ FEATURES - Modules specify invariants and operations, preferably in an x/[module]/simulation package - Modules can test random combinations of their own operations - Applications can integrate operations and invariants from modules together for an integrated simulation + - Simulates Tendermint's algorithm for validator set updates + - Simulates validator signing/downtime with a Markov chain, and occaisional double-signatures + - Includes simulated operations & invariants for staking, slashing, governance, and bank modules - [store] \#1481 Add transient store - [baseapp] Initialize validator set on ResponseInitChain - [baseapp] added BaseApp.Seal - ability to seal baseapp parameters once they've been set diff --git a/Gopkg.lock b/Gopkg.lock index cc42ac4f4..c3a540858 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -262,7 +263,7 @@ version = "v1.0.0" [[projects]] - digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +274,7 @@ [[projects]] branch = "master" - digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +282,7 @@ [[projects]] branch = "master" - digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +294,7 @@ [[projects]] branch = "master" - digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +313,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +332,7 @@ version = "v1.2.0" [[projects]] - digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -340,11 +341,11 @@ [[projects]] branch = "master" - digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] pruneopts = "UT" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" @@ -363,7 +364,7 @@ version = "v1.0.0" [[projects]] - digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +376,7 @@ [[projects]] branch = "master" - digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" + digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -392,11 +393,11 @@ "leveldb/util", ] pruneopts = "UT" - revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" + revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" [[projects]] branch = "master" - digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +424,7 @@ version = "v0.9.2" [[projects]] - digest = "1:df232b6f3c44554161093af004100f75e564b398ad3ff63ecbc297fe400dcfdb" + digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +499,7 @@ [[projects]] branch = "master" - digest = "1:3c3c47c1f7587c380afcc1d76385a4a03a2917b9ccc1ac50864d8f87e0264ada" + digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -520,7 +521,7 @@ revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -537,17 +538,17 @@ [[projects]] branch = "master" - digest = "1:a97b28c54844d6b9848a840ae83d4d263292e831e8c2a586116fcab5c7cfe5f2" + digest = "1:a989b95f72fce8876213e8e20492525b4cf69a9e7fee7f1d9897983ee0d547e9" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "98c5dad5d1a0e8a73845ecc8897d0bd56586511d" + revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded" [[projects]] - digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -575,10 +576,10 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "383e8b2c3b9e36c4076b235b32537292176bae20" + revision = "d0a8f471bba2dbb160885b0000d814ee5d559bad" [[projects]] - digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", diff --git a/Makefile b/Makefile index 208b59ade..d06d4eb4c 100644 --- a/Makefile +++ b/Makefile @@ -130,15 +130,17 @@ test_unit: test_race: @go test -race $(PACKAGES_NOSIMULATION) -test_sim: - @echo "Running individual module simulations." - @go test $(PACKAGES_SIMTEST) -v - @echo "Running full Gaia simulation. This may take several minutes." - @echo "Pass the flag 'SimulationSeed' to run with a constant seed." - @echo "Pass the flag 'SimulationNumKeys' to run with the specified number of keys." - @echo "Pass the flag 'SimulationNumBlocks' to run with the specified number of blocks." - @echo "Pass the flag 'SimulationBlockSize' to run with the specified block size (operations per block)." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationBlockSize=200 -v +test_sim_modules: + @echo "Running individual module simulations..." + @go test $(PACKAGES_SIMTEST) + +test_sim_gaia_fast: + @echo "Running full Gaia simulation. This may take several minutes..." + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -v -timeout 24h + +test_sim_gaia_slow: + @echo "Running full Gaia simulation. This may take several minutes..." + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h test_cover: @bash tests/test_cover.sh @@ -204,4 +206,4 @@ localnet-stop: check_tools check_dev_tools get_tools get_dev_tools get_vendor_deps draw_deps test test_cli test_unit \ test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \ build-linux build-docker-gaiadnode localnet-start localnet-stop \ -format check-ledger test_sim update_tools update_dev_tools +format check-ledger test_sim_modules test_sim_gaia_fast test_sim_gaia_slow update_tools update_dev_tools diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index d7398d899..cf63f1f4d 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -379,7 +379,7 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg } else { // In the first block, app.deliverState.ctx will already be initialized // by InitChain. Context is now updated with Header information. - app.deliverState.ctx = app.deliverState.ctx.WithBlockHeader(req.Header) + app.deliverState.ctx = app.deliverState.ctx.WithBlockHeader(req.Header).WithBlockHeight(req.Header.Height) } if app.beginBlocker != nil { diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index f0bea1e17..5d0edcba2 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -8,47 +8,68 @@ import ( "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" + govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/mock/simulation" + slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation" stake "github.com/cosmos/cosmos-sdk/x/stake" stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation" ) var ( seed int64 - numKeys int numBlocks int blockSize int enabled bool + verbose bool ) func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") - flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") - flag.IntVar(&blockSize, "SimulationBlockSize", 100, "Operations per block") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 500, "Number of blocks") + flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") + flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") } -func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { +func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { var genesisAccounts []GenesisAccount // Randomly generate some genesis accounts - for _, addr := range accs { + for _, acc := range accs { coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(100)}} genesisAccounts = append(genesisAccounts, GenesisAccount{ - Address: addr, + Address: acc, Coins: coins, }) } // Default genesis state stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000) + var validators []stake.Validator + var delegations []stake.Delegation + // XXX Try different numbers of initially bonded validators + numInitiallyBonded := int64(50) + for i := 0; i < int(numInitiallyBonded); i++ { + validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) + validator.Tokens = sdk.NewRat(100) + validator.DelegatorShares = sdk.NewRat(100) + delegation := stake.Delegation{accs[i], accs[i], sdk.NewRat(100), 0} + validators = append(validators, validator) + delegations = append(delegations, delegation) + } + stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*250) + (numInitiallyBonded * 100)) + stakeGenesis.Validators = validators + stakeGenesis.Bonds = delegations + // No inflation, for now + stakeGenesis.Params.InflationMax = sdk.NewRat(0) + stakeGenesis.Params.InflationMin = sdk.NewRat(0) genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, @@ -69,16 +90,31 @@ func TestFullGaiaSimulation(t *testing.T) { } // Setup Gaia application - logger := log.NewNopLogger() + var logger log.Logger + if verbose { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } db := dbm.NewMemDB() app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) + allInvariants := func(t *testing.T, baseapp *baseapp.BaseApp, log string) { + banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) + govsim.AllInvariants()(t, baseapp, log) + stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) + slashingsim.AllInvariants()(t, baseapp, log) + } + // Run randomized simulation simulation.SimulateFromSeed( t, app.BaseApp, appStateFn, seed, []simulation.TestAndRunTx{ banksim.TestAndRunSingleInputMsgSend(app.accountMapper), + govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgEditValidator(app.stakeKeeper), stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), @@ -86,15 +122,57 @@ func TestFullGaiaSimulation(t *testing.T) { stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), }, []simulation.RandSetup{}, []simulation.Invariant{ - banksim.NonnegativeBalanceInvariant(app.accountMapper), - stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper), + allInvariants, }, - numKeys, numBlocks, blockSize, ) } + +// TODO: Make this not depend on Gaia or any of the modules, +// and place it in random_simulation_test.go +// +// Test doesn't use `app.ExportAppStateAndValidators` as that panics with the following: +// panic: Stored pool should not have been nil [recovered] +// panic: Stored pool should not have been nil +// Change to `app.ExportAppStateAndValidators` once it is fixed +func TestAppStateDeterminism(t *testing.T) { + numTimesToRun := 5 + appHashList := make([]json.RawMessage, numTimesToRun) + + seed := rand.Int63() + for i := 0; i < numTimesToRun; i++ { + logger := log.NewNopLogger() + db := dbm.NewMemDB() + app := NewGaiaApp(logger, db, nil) + + noOpInvariant := func(t *testing.T, baseapp *baseapp.BaseApp, log string) {} + noOpTestAndRunTx := func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + privKeys []crypto.PrivKey, log string, event func(string), + ) (action string, err sdk.Error) { + return "", nil + } + + // Run randomized simulation + simulation.SimulateFromSeed( + t, app.BaseApp, appStateFn, seed, + []simulation.TestAndRunTx{ + noOpTestAndRunTx, + }, + []simulation.RandSetup{}, + []simulation.Invariant{noOpInvariant}, + 0, + 10, + ) + appHash := app.LastCommitID().Hash + appHashList[i] = appHash + } + for i := 1; i < numTimesToRun; i++ { + require.Equal(t, appHashList[0], appHashList[i]) + } +} diff --git a/tests/test_cover.sh b/tests/test_cover.sh index be6215b5a..3fb0ab69c 100644 --- a/tests/test_cover.sh +++ b/tests/test_cover.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test) +PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation') set -e echo "mode: atomic" > coverage.txt diff --git a/types/stake.go b/types/stake.go index 4e3cf38a3..f611a2b51 100644 --- a/types/stake.go +++ b/types/stake.go @@ -51,8 +51,9 @@ type Validator interface { // validator which fulfills abci validator interface for use in Tendermint func ABCIValidator(v Validator) abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), - Power: v.GetPower().RoundInt64(), + PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), + Address: v.GetPubKey().Address(), + Power: v.GetPower().RoundInt64(), } } diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 3a7248875..43d7e1fd7 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -35,6 +35,10 @@ func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.TestAndR toAddr := sdk.AccAddress(toKey.PubKey().Address()) initFromCoins := mapper.GetAccount(ctx, fromAddr).GetCoins() + if len(initFromCoins) == 0 { + return "skipping, no coins at all", nil + } + denomIndex := r.Intn(len(initFromCoins)) amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) if goErr != nil { diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 5d76dd058..49e3dfa92 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -5,6 +5,8 @@ import ( "math/rand" "testing" + "github.com/tendermint/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/mock" @@ -24,7 +26,7 @@ func TestBankWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } @@ -39,6 +41,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, + 30, 30, ) } diff --git a/x/gov/handler.go b/x/gov/handler.go index a9fdfcb3c..554c06a8a 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -96,6 +96,8 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result { // Called every block, process inflation, update validator set func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { + logger := ctx.Logger().With("module", "x/gov") + resTags = sdk.NewTags() // Delete proposals that haven't met minDeposit @@ -109,6 +111,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { keeper.DeleteProposal(ctx, inactiveProposal) resTags.AppendTag(tags.Action, tags.ActionProposalDropped) resTags.AppendTag(tags.ProposalID, proposalIDBytes) + + logger.Info("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted", + inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit()) } // Check if earliest Active Proposal ended voting period yet @@ -136,6 +141,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { activeProposal.SetTallyResult(tallyResults) keeper.SetProposal(ctx, activeProposal) + logger.Info("Proposal %d - \"%s\" - tallied, passed: %v", + activeProposal.GetProposalID(), activeProposal.GetTitle(), passes) + for _, valAddr := range nonVotingVals { val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) keeper.ds.GetValidatorSet().Slash(ctx, @@ -143,6 +151,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { ctx.BlockHeight(), val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) + + logger.Info("Validator %s failed to vote on proposal %d, slashing", + val.GetOwner(), activeProposal.GetProposalID()) } resTags.AppendTag(tags.Action, action) diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 0034e3d71..8a23ad248 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -119,6 +119,18 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk return nil } +// Get the last used proposal ID +func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) { + store := ctx.KVStore(keeper.storeKey) + bz := store.Get(KeyNextProposalID) + if bz == nil { + return 0 + } + keeper.cdc.MustUnmarshalBinary(bz, &proposalID) + proposalID-- + return +} + func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) { store := ctx.KVStore(keeper.storeKey) bz := store.Get(KeyNextProposalID) diff --git a/x/gov/simulation/invariants.go b/x/gov/simulation/invariants.go new file mode 100644 index 000000000..e9275f3c1 --- /dev/null +++ b/x/gov/simulation/invariants.go @@ -0,0 +1,19 @@ +package simulation + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +// AllInvariants tests all governance invariants +func AllInvariants() simulation.Invariant { + return func(t *testing.T, app *baseapp.BaseApp, log string) { + // TODO Add some invariants! + // Checking proposal queues, no passed-but-unexecuted proposals, etc. + require.Nil(t, nil) + } +} diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go new file mode 100644 index 000000000..596a013d3 --- /dev/null +++ b/x/gov/simulation/msgs.go @@ -0,0 +1,132 @@ +package simulation + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +const ( + denom = "steak" +) + +// SimulateMsgSubmitProposal +func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + key := simulation.RandomKey(r, keys) + addr := sdk.AccAddress(key.PubKey().Address()) + deposit := randomDeposit(r) + msg := gov.NewMsgSubmitProposal( + simulation.RandStringOfLength(r, 5), + simulation.RandStringOfLength(r, 5), + gov.ProposalTypeText, + addr, + deposit, + ) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + // Update pool to keep invariants + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + sk.SetPool(ctx, pool) + write() + } + event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgDeposit +func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + key := simulation.RandomKey(r, keys) + addr := sdk.AccAddress(key.PubKey().Address()) + proposalID, ok := randomProposalID(r, k, ctx) + if !ok { + return "no-operation", nil + } + deposit := randomDeposit(r) + msg := gov.NewMsgDeposit(addr, proposalID, deposit) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + // Update pool to keep invariants + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + sk.SetPool(ctx, pool) + write() + } + event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgVote +func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + key := simulation.RandomKey(r, keys) + addr := sdk.AccAddress(key.PubKey().Address()) + proposalID, ok := randomProposalID(r, k, ctx) + if !ok { + return "no-operation", nil + } + option := randomVotingOption(r) + msg := gov.NewMsgVote(addr, proposalID, option) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} + +// Pick a random deposit +func randomDeposit(r *rand.Rand) sdk.Coins { + // TODO Choose based on account balance and min deposit + amount := int64(r.Intn(20)) + 1 + return sdk.Coins{sdk.NewInt64Coin(denom, amount)} +} + +// Pick a random proposal ID +func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID int64, ok bool) { + lastProposalID := k.GetLastProposalID(ctx) + if lastProposalID < 1 { + return 0, false + } + proposalID = int64(r.Intn(int(lastProposalID))) + return proposalID, true +} + +// Pick a random voting option +func randomVotingOption(r *rand.Rand) gov.VoteOption { + switch r.Intn(4) { + case 0: + return gov.OptionYes + case 1: + return gov.OptionAbstain + case 2: + return gov.OptionNo + case 3: + return gov.OptionNoWithVeto + } + panic("should not happen") +} diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go new file mode 100644 index 000000000..e7131f8fc --- /dev/null +++ b/x/gov/simulation/sim_test.go @@ -0,0 +1,68 @@ +package simulation + +import ( + "encoding/json" + "math/rand" + "testing" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +// TestGovWithRandomMessages +func TestGovWithRandomMessages(t *testing.T) { + mapp := mock.NewApp() + + bank.RegisterWire(mapp.Cdc) + gov.RegisterWire(mapp.Cdc) + mapper := mapp.AccountMapper + coinKeeper := bank.NewKeeper(mapper) + stakeKey := sdk.NewKVStoreKey("stake") + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, coinKeeper, stake.DefaultCodespace) + paramKey := sdk.NewKVStoreKey("params") + paramKeeper := params.NewKeeper(mapp.Cdc, paramKey) + govKey := sdk.NewKVStoreKey("gov") + govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), coinKeeper, stakeKeeper, gov.DefaultCodespace) + mapp.Router().AddRoute("gov", gov.NewHandler(govKeeper)) + mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + gov.EndBlocker(ctx, govKeeper) + return abci.ResponseEndBlock{} + }) + + err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey, paramKey, govKey}) + if err != nil { + panic(err) + } + + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { + mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) + return json.RawMessage("{}") + } + + setup := func(r *rand.Rand, privKeys []crypto.PrivKey) { + ctx := mapp.NewContext(false, abci.Header{}) + stake.InitGenesis(ctx, stakeKeeper, stake.DefaultGenesisState()) + gov.InitGenesis(ctx, govKeeper, gov.DefaultGenesisState()) + } + + simulation.Simulate( + t, mapp.BaseApp, appStateFn, + []simulation.TestAndRunTx{ + SimulateMsgSubmitProposal(govKeeper, stakeKeeper), + SimulateMsgDeposit(govKeeper, stakeKeeper), + SimulateMsgVote(govKeeper, stakeKeeper), + }, []simulation.RandSetup{ + setup, + }, []simulation.Invariant{ + AllInvariants(), + }, 10, 100, + ) +} diff --git a/x/mock/app.go b/x/mock/app.go index 53b6345b0..f472c5531 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -11,6 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" ) @@ -173,7 +174,32 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA keys = make([]crypto.PrivKey, n, n) addrs = make([]sdk.AccAddress, n, n) for i := 0; i < n; i++ { - keys[i] = ed25519.GenPrivKey() + if rand.Int63()%2 == 0 { + keys[i] = secp256k1.GenPrivKey() + } else { + keys[i] = ed25519.GenPrivKey() + } + addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) + } + return +} + +// GeneratePrivKeyAddressPairsFromRand generates a total of n private key, address +// pairs using the provided randomness source. +func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) { + keys = make([]crypto.PrivKey, n, n) + addrs = make([]sdk.AccAddress, n, n) + for i := 0; i < n; i++ { + secret := make([]byte, 32) + _, err := rand.Read(secret) + if err != nil { + panic("Could not read randomness") + } + if rand.Int63()%2 == 0 { + keys[i] = secp256k1.GenPrivKeySecp256k1(secret) + } else { + keys[i] = ed25519.GenPrivKeyFromSecret(secret) + } addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) } return diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go new file mode 100644 index 000000000..985a22dca --- /dev/null +++ b/x/mock/simulation/constants.go @@ -0,0 +1,31 @@ +package simulation + +const ( + // Fraction of double-signing evidence from a past height + pastEvidenceFraction float64 = 0.5 + + // Minimum time per block + minTimePerBlock int64 = 86400 / 2 + + // Maximum time per block + maxTimePerBlock int64 = 86400 + + // Number of keys + numKeys int = 250 + + // Chance that double-signing evidence is found on a given block + evidenceFraction float64 = 0.01 + + // TODO Remove in favor of binary search for invariant violation + onOperation bool = false +) + +var ( + // Currently there are 3 different liveness types, fully online, spotty connection, offline. + initialLivenessWeightings = []int{40, 5, 5} + livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{ + {90, 20, 1}, + {10, 50, 5}, + {0, 10, 1000}, + }) +) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 5f507b89c..1b6953631 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -7,75 +7,211 @@ import ( "testing" "time" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + tmtypes "github.com/tendermint/tendermint/types" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" ) // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, + invariants []Invariant, numBlocks int, blockSize int, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize) } // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, + invariants []Invariant, numBlocks int, blockSize int, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) - keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) + fmt.Printf("%s\n", log) r := rand.New(rand.NewSource(seed)) + keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) // Setup event stats events := make(map[string]uint) event := func(what string) { + log += "\nevent - " + what events[what]++ } - app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) + timestamp := time.Unix(0, 0) + timeDiff := maxTimePerBlock - minTimePerBlock + + res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) + validators := make(map[string]mockValidator) + for _, validator := range res.Validators { + validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)} + } + for i := 0; i < len(setups); i++ { setups[i](r, keys) } - app.Commit() - header := abci.Header{Height: 0} + header := abci.Header{Height: 0, Time: timestamp} + opCount := 0 + + request := abci.RequestBeginBlock{Header: header} + + var pastTimes []time.Time for i := 0; i < numBlocks; i++ { - app.BeginBlock(abci.RequestBeginBlock{}) - // Make sure invariants hold at beginning of block and when nothing was - // done. + // Log the header time for future lookup + pastTimes = append(pastTimes, header.Time) + + // Run the BeginBlock handler + app.BeginBlock(request) + + log += "\nBeginBlock" + + // Make sure invariants hold at beginning of block AssertAllInvariants(t, app, invariants, log) ctx := app.NewContext(false, header) - // TODO: Add modes to simulate "no load", "medium load", and - // "high load" blocks. - for j := 0; j < blockSize; j++ { + var thisBlockSize int + load := r.Float64() + switch { + case load < 0.33: + thisBlockSize = 0 + case load < 0.66: + thisBlockSize = r.Intn(blockSize * 2) + default: + thisBlockSize = r.Intn(blockSize * 4) + } + for j := 0; j < thisBlockSize; j++ { logUpdate, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) log += "\n" + logUpdate require.Nil(t, err, log) - AssertAllInvariants(t, app, invariants, log) + if onOperation { + AssertAllInvariants(t, app, invariants, log) + } + if opCount%200 == 0 { + fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + } + opCount++ } - app.EndBlock(abci.RequestEndBlock{}) + res := app.EndBlock(abci.RequestEndBlock{}) header.Height++ + header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) + + log += "\nEndBlock" + + // Make sure invariants hold at end of block + AssertAllInvariants(t, app, invariants, log) + + // Generate a random RequestBeginBlock with the current validator set for the next block + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) + + // Update the validator set + validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) } + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) DisplayEvents(events) } +// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction +func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, + pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { + if len(validators) == 0 { + return abci.RequestBeginBlock{Header: header} + } + signingValidators := make([]abci.SigningValidator, len(validators)) + i := 0 + for _, mVal := range validators { + mVal.livenessState = livenessTransitions.NextState(r, mVal.livenessState) + signed := true + + if mVal.livenessState == 1 { + // spotty connection, 50% probability of success + // See https://github.com/golang/go/issues/23804#issuecomment-365370418 + // for reasoning behind computing like this + signed = r.Int63()%2 == 0 + } else if mVal.livenessState == 2 { + // offline + signed = false + } + if signed { + event("beginblock/signing/signed") + } else { + event("beginblock/signing/missed") + } + signingValidators[i] = abci.SigningValidator{ + Validator: mVal.val, + SignedLastBlock: signed, + } + i++ + } + evidence := make([]abci.Evidence, 0) + for r.Float64() < evidenceFraction { + height := header.Height + time := header.Time + if r.Float64() < pastEvidenceFraction { + height = int64(r.Intn(int(header.Height))) + time = pastTimes[height] + } + validator := signingValidators[r.Intn(len(signingValidators))].Validator + var currentTotalVotingPower int64 + for _, mVal := range validators { + currentTotalVotingPower += mVal.val.Power + } + evidence = append(evidence, abci.Evidence{ + Type: tmtypes.ABCIEvidenceTypeDuplicateVote, + Validator: validator, + Height: height, + Time: time, + TotalVotingPower: currentTotalVotingPower, + }) + event("beginblock/evidence") + } + return abci.RequestBeginBlock{ + Header: header, + LastCommitInfo: abci.LastCommitInfo{ + Validators: signingValidators, + }, + ByzantineValidators: evidence, + } +} + // AssertAllInvariants asserts a list of provided invariants against application state func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, log string) { for i := 0; i < len(tests); i++ { tests[i](t, app, log) } } + +// updateValidators mimicks Tendermint's update logic +func updateValidators(t *testing.T, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator { + for _, update := range updates { + switch { + case update.Power == 0: + require.NotNil(t, current[string(update.PubKey.Data)], "tried to delete a nonexistent validator") + event("endblock/validatorupdates/kicked") + delete(current, string(update.PubKey.Data)) + default: + // Does validator already exist? + if mVal, ok := current[string(update.PubKey.Data)]; ok { + mVal.val = update + event("endblock/validatorupdates/updated") + } else { + // Set this new validator + current[string(update.PubKey.Data)] = mockValidator{update, GetMemberOfInitialState(r, initialLivenessWeightings)} + event("endblock/validatorupdates/added") + } + } + } + return current +} diff --git a/x/mock/simulation/transition_matrix.go b/x/mock/simulation/transition_matrix.go new file mode 100644 index 000000000..39bdb1e4f --- /dev/null +++ b/x/mock/simulation/transition_matrix.go @@ -0,0 +1,70 @@ +package simulation + +import ( + "fmt" + "math/rand" +) + +// TransitionMatrix is _almost_ a left stochastic matrix. +// It is technically not one due to not normalizing the column values. +// In the future, if we want to find the steady state distribution, +// it will be quite easy to normalize these values to get a stochastic matrix. +// Floats aren't currently used as the default due to non-determinism across +// architectures +type TransitionMatrix struct { + weights [][]int + // total in each column + totals []int + n int +} + +// CreateTransitionMatrix creates a transition matrix from the provided weights. +// TODO: Provide example usage +func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) { + n := len(weights) + for i := 0; i < n; i++ { + if len(weights[i]) != n { + return TransitionMatrix{}, fmt.Errorf("Transition Matrix: Non-square matrix provided, error on row %d", i) + } + } + totals := make([]int, n) + for row := 0; row < n; row++ { + for col := 0; col < n; col++ { + totals[col] += weights[row][col] + } + } + return TransitionMatrix{weights, totals, n}, nil +} + +// NextState returns the next state randomly chosen using r, and the weightings provided +// in the transition matrix. +func (t TransitionMatrix) NextState(r *rand.Rand, i int) int { + randNum := r.Intn(t.totals[i]) + for row := 0; row < t.n; row++ { + if randNum < t.weights[row][i] { + return row + } + randNum -= t.weights[row][i] + } + // This line should never get executed + return -1 +} + +// GetMemberOfInitialState takes an initial array of weights, of size n. +// It returns a weighted random number in [0,n). +func GetMemberOfInitialState(r *rand.Rand, weights []int) int { + n := len(weights) + total := 0 + for i := 0; i < n; i++ { + total += weights[i] + } + randNum := r.Intn(total) + for state := 0; state < n; state++ { + if randNum < weights[state] { + return state + } + randNum -= weights[state] + } + // This line should never get executed + return -1 +} diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 6e1d9f198..35769b0b2 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" ) @@ -25,6 +26,11 @@ type ( // If the invariant has been broken, the function should halt the // test and output the log. Invariant func(t *testing.T, app *baseapp.BaseApp, log string) + + mockValidator struct { + val abci.Validator + livenessState int + } ) // PeriodicInvariant returns an Invariant function closure that asserts diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index 14227a1ae..1d64ba30d 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -3,8 +3,9 @@ package simulation import ( "fmt" "math/rand" + "sort" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -39,8 +40,15 @@ func RandStringOfLength(r *rand.Rand, n int) string { // Pretty-print events as a table func DisplayEvents(events map[string]uint) { - // TODO - fmt.Printf("Events: %v\n", events) + var keys []string + for key := range events { + keys = append(keys, key) + } + sort.Strings(keys) + fmt.Printf("Event statistics: \n") + for _, key := range keys { + fmt.Printf(" % 60s => %d\n", key, events[key]) + } } // Pick a random key from an array diff --git a/x/slashing/simulation/invariants.go b/x/slashing/simulation/invariants.go new file mode 100644 index 000000000..7352aa503 --- /dev/null +++ b/x/slashing/simulation/invariants.go @@ -0,0 +1,18 @@ +package simulation + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +// AllInvariants tests all slashing invariants +func AllInvariants() simulation.Invariant { + return func(t *testing.T, app *baseapp.BaseApp, log string) { + // TODO Any invariants to check here? + require.Nil(t, nil) + } +} diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go new file mode 100644 index 000000000..b6a093674 --- /dev/null +++ b/x/slashing/simulation/msgs.go @@ -0,0 +1,34 @@ +package simulation + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/slashing" +) + +// SimulateMsgUnrevoke +func SimulateMsgUnrevoke(k slashing.Keeper) simulation.TestAndRunTx { + return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { + key := simulation.RandomKey(r, keys) + address := sdk.AccAddress(key.PubKey().Address()) + msg := slashing.NewMsgUnrevoke(address) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := slashing.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("slashing/MsgUnrevoke/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgUnrevoke: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} diff --git a/x/stake/genesis.go b/x/stake/genesis.go index 46bda752d..7a004bccd 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -33,7 +33,6 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ // Manually set indexes for the first time keeper.SetValidatorByPubKeyIndex(ctx, validator) - keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) if validator.Status == sdk.Bonded { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index eaaf3df9e..8b8cea73d 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -421,6 +421,9 @@ func (k Keeper) UpdateBondedValidators( if !validator.Revoked { if validator.Status != sdk.Bonded { validatorToBond = validator + if newValidatorBonded { + panic("already decided to bond a validator, can't bond another!") + } newValidatorBonded = true } @@ -436,6 +439,10 @@ func (k Keeper) UpdateBondedValidators( iterator.Close() + if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) { + panic("cliff validator has not been changed, yet we bonded a new validator") + } + // clear or set the cliff validator if bondedValidatorsCount == int(maxValidators) { k.setCliffValidator(ctx, validator, k.GetPool(ctx)) @@ -556,7 +563,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // sanity check if validator.Status == sdk.Unbonded { - panic(fmt.Sprintf("should not already be unbonded, validator: %v\n", validator)) + panic(fmt.Sprintf("should not already be unbonded, validator: %v\n", validator)) } // set the status diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index e4077a749..ec39f87b0 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -235,7 +235,10 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { return func(r *rand.Rand, privKeys []crypto.PrivKey) { ctx := mapp.NewContext(false, abci.Header{}) - stake.InitGenesis(ctx, k, stake.DefaultGenesisState()) + gen := stake.DefaultGenesisState() + gen.Params.InflationMax = sdk.NewRat(0) + gen.Params.InflationMin = sdk.NewRat(0) + stake.InitGenesis(ctx, k, gen) params := k.GetParams(ctx) denom := params.BondDenom loose := sdk.ZeroInt() diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 391ca1996..3e80e1eb3 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -5,12 +5,14 @@ import ( "math/rand" "testing" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/cosmos/cosmos-sdk/x/mock/simulation" "github.com/cosmos/cosmos-sdk/x/stake" - abci "github.com/tendermint/tendermint/abci/types" ) // TestStakeWithRandomMessages @@ -35,7 +37,7 @@ func TestStakeWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } @@ -54,6 +56,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, + }, 10, 100, ) } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 837b8f8e8..089e8ea92 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -314,8 +314,9 @@ func (d Description) EnsureLength() (Description, sdk.Error) { // ABCIValidator returns an abci.Validator from a staked validator type. func (v Validator) ABCIValidator() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Power: v.BondedTokens().RoundInt64(), + PubKey: tmtypes.TM2PB.PubKey(v.PubKey), + Address: v.PubKey.Address(), + Power: v.BondedTokens().RoundInt64(), } } @@ -323,8 +324,9 @@ func (v Validator) ABCIValidator() abci.Validator { // with with zero power used for validator updates. func (v Validator) ABCIValidatorZero() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Power: 0, + PubKey: tmtypes.TM2PB.PubKey(v.PubKey), + Address: v.PubKey.Address(), + Power: 0, } } From 45bd414fc2fffaa0aee9548087352c84dd8364e9 Mon Sep 17 00:00:00 2001 From: Jack Zampolin <jack.zampolin@gmail.com> Date: Thu, 16 Aug 2018 11:23:57 -0700 Subject: [PATCH 53/97] Run localnet on every commit ensure network reaches at least 10 blocks (#2067) --- .circleci/config.yml | 26 +++++++++++++++++++++ CHANGELOG.md | 1 + Makefile | 4 ++-- PENDING.md | 19 ++++++++------- scripts/localnet-blocks-test.sh | 41 +++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 12 deletions(-) create mode 100755 scripts/localnet-blocks-test.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index b778653ea..3be6151e9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -165,6 +165,29 @@ jobs: name: upload command: bash <(curl -s https://codecov.io/bash) -f coverage.txt + localnet: + working_directory: /home/circleci/.go_workspace/src/github.com/cosmos/cosmos-sdk + machine: + image: circleci/classic:latest + environment: + GOBIN: /home/circleci/.go_workspace/bin + GOPATH: /home/circleci/.go_workspace/ + GOOS: linux + GOARCH: amd64 + parallelism: 1 + steps: + - checkout + - run: + name: run localnet and exit on failure + command: | + set -x + make get_tools + make get_vendor_deps + make build-linux + make localnet-start + ./scripts/localnet-blocks-test.sh 40 5 10 localhost + + workflows: version: 2 test-suite: @@ -185,6 +208,9 @@ workflows: - test_cover: requires: - setup_dependencies + - localnet: + requires: + - setup_dependencies - upload_coverage: requires: - test_cover diff --git a/CHANGELOG.md b/CHANGELOG.md index b4de50494..55104830b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ IMPROVEMENTS - [x/gov] Initial governance parameters can now be set in the genesis file - [x/stake] \#1815 Sped up the processing of `EditValidator` txs. - [config] \#1930 Transactions indexer indexes all tags by default. + - [ci] [#2057](https://github.com/cosmos/cosmos-sdk/pull/2057) Run `make localnet-start` on every commit and ensure network reaches at least 10 blocks * SDK - [baseapp] \#1587 Allow any alphanumeric character in route diff --git a/Makefile b/Makefile index d06d4eb4c..655d8574e 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ ci: get_tools get_vendor_deps install test_cover test_lint test ######################################## ### Build/Install -check-ledger: +check-ledger: ifeq ($(LEDGER_ENABLED),true) ifndef GCC $(error "gcc not installed for ledger support, please install") @@ -193,7 +193,7 @@ build-docker-gaiadnode: # Run a 4-node testnet locally localnet-start: localnet-stop @if ! [ -f build/node0/gaiad/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/gaiad:Z tendermint/gaiadnode testnet --v 4 --o . --starting-ip-address 192.168.10.2 ; fi - docker-compose up + docker-compose up -d # Stop testnet localnet-stop: diff --git a/PENDING.md b/PENDING.md index 9f0b86a99..9ade31c8b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,10 +8,10 @@ BREAKING CHANGES * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) - -* SDK -* Tendermint +* SDK + +* Tendermint FEATURES @@ -22,9 +22,9 @@ FEATURES * Gaia -* SDK +* SDK -* Tendermint +* Tendermint IMPROVEMENTS @@ -35,9 +35,9 @@ IMPROVEMENTS * Gaia -* SDK +* SDK -* Tendermint +* Tendermint BUG FIXES @@ -48,7 +48,6 @@ BUG FIXES * Gaia -* SDK - -* Tendermint +* SDK +* Tendermint diff --git a/scripts/localnet-blocks-test.sh b/scripts/localnet-blocks-test.sh new file mode 100755 index 000000000..53df090ff --- /dev/null +++ b/scripts/localnet-blocks-test.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +CNT=0 +ITER=$1 +SLEEP=$2 +NUMBLOCKS=$3 +NODEADDR=$4 + +if [ -z "$1" ]; then + echo "Need to input number of iterations to run..." + exit 1 +fi + +if [ -z "$2" ]; then + echo "Need to input number of seconds to sleep between iterations" + exit 1 +fi + +if [ -z "$3" ]; then + echo "Need to input block height to declare completion..." + exit 1 +fi + +if [ -z "$4" ]; then + echo "Need to input node address to poll..." + exit 1 +fi + +while [ ${CNT} -lt $ITER ]; do + var=$(curl -s $NODEADDR:26657/status | jq -r '.result.sync_info.latest_block_height') + echo "Number of Blocks: ${var}" + if [ ! -z ${var} ] && [ ${var} -gt ${NUMBLOCKS} ]; then + echo "Number of blocks reached, exiting success..." + exit 0 + fi + let CNT=CNT+1 + sleep $SLEEP +done + +echo "Timeout reached, exiting failure..." +exit 1 From c79e130d0fbabea6dae0fca5d4c47dabb66f79f9 Mon Sep 17 00:00:00 2001 From: Aditya Sripal <adityasripal@gmail.com> Date: Thu, 16 Aug 2018 12:07:09 -0700 Subject: [PATCH 54/97] jae comments --- docs/spec/auth/vesting.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/spec/auth/vesting.md b/docs/spec/auth/vesting.md index 344e10049..c5c25ecae 100644 --- a/docs/spec/auth/vesting.md +++ b/docs/spec/auth/vesting.md @@ -29,20 +29,20 @@ type VestingAccount interface { // Continuously vests by unlocking coins linearly with respect to time type ContinuousVestingAccount struct { BaseAccount - OriginalCoins sdk.Coins // Coins in account on Initialization - ReceivedCoins sdk.Coins // Coins received from other accounts - SentCoins sdk.Coins // Coins sent to other accounts + OriginalVestingCoins sdk.Coins // Coins in account on Initialization + ReceivedCoins sdk.Coins // Coins received from other accounts + SentCoins sdk.Coins // Coins sent to other accounts // StartTime and EndTime used to calculate how much of OriginalCoins is unlocked at any given point - StartTime time.Time - EndTime time.Time + StartTime time.Time + EndTime time.Time } // Uses time in context to calculate total unlocked coins SendableCoins(vacc ContinuousVestingAccount, ctx sdk.Context) sdk.Coins: // Coins unlocked by vesting schedule - unlockedCoins := ReceivedCoins - SentCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime) + unlockedCoins := ReceivedCoins - SentCoins + OriginalVestingCoins * (Now - StartTime) / (EndTime - StartTime) // Must still check for currentCoins constraint since some unlocked coins may have been delegated. currentCoins := vacc.BaseAccount.GetCoins() @@ -60,11 +60,11 @@ vacc, ok := acc.(VestingAccount); ok as well as to calculate the SendableCoins at any given moment. -The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalCoins`, `ReceivedCoins`, +The `ContinuousVestingAccount` struct implements the Vesting account interface. It uses `OriginalVestingCoins`, `ReceivedCoins`, `SentCoins`, `StartTime`, and `EndTime` to calculate how many coins are sendable at any given point. Since the vesting restrictions need to be implemented on a per-module basis, the `ContinuousVestingAccount` implements the `Account` interface exactly like `BaseAccount`. Thus, `ContinuousVestingAccount.GetCoins()` will return the total of -both locked coins and unlocked coins currently in the account. +both locked coins and unlocked coins currently in the account. Delegated coins are deducted from `Account.GetCoins()`, but do not count against unlocked coins because they are still at stake and will be reinstated (partially if slashed) after waiting the full unbonding period. ##### Changes to Keepers/Handler @@ -93,8 +93,8 @@ immediately after receiving them. Thus, handlers (like staking or bank) that sen originally own should increment `ReceivedCoins` by the amount sent. Unlocked coins that are sent to other accounts will increment the vesting account's `SentCoins` attribute. -CONTRACT: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account unbonds from a validator, their tokens should be added back to account but `ReceivedCoins` SHOULD NOT be incremented. -However when the staking handler is handing out fees/inflation rewards or a user sends coins to vesting account, then `ReceivedCoins` SHOULD be incremented. +CONTRACT: Handlers SHOULD NOT update `ReceivedCoins` if they were originally sent from the vesting account. For example, if a vesting account unbonds from a validator, their tokens should be added back to account but staking handlers SHOULD NOT update `ReceivedCoins`. +However when a user sends coins to vesting account, then `ReceivedCoins` SHOULD be incremented. ### Initializing at Genesis @@ -117,10 +117,10 @@ initChainer: } if gacc.EndTime != 0: vestingAccount := ContinuouslyVestingAccount{ - BaseAccount: baseAccount, - OriginalCoins: gacc.GenesisCoins, - StartTime: RequestInitChain.Time, - EndTime: gacc.EndTime, + BaseAccount: baseAccount, + OriginalVestingCoins: gacc.GenesisCoins, + StartTime: RequestInitChain.Time, + EndTime: gacc.EndTime, } AddAccountToState(vestingAccount) else: @@ -130,7 +130,7 @@ initChainer: ### Formulas -`OriginalCoins`: Amount of coins in account at Genesis +`OriginalVestingCoins`: Amount of coins in account at Genesis `CurrentCoins`: Coins currently in the baseaccount (both locked and unlocked: `vestingAccount.GetCoins`) @@ -144,16 +144,16 @@ initChainer: Maximum amount of coins vesting schedule allows to be sent: -`ReceivedCoins - SentCoins + OriginalCoins * (Now - StartTime) / (EndTime - StartTime)` +`ReceivedCoins - SentCoins + OriginalVestingCoins * (Now - StartTime) / (EndTime - StartTime)` -`ReceivedCoins - SentCoins + OriginalCoins - LockedCoins` +`ReceivedCoins - SentCoins + OriginalVestingCoins - LockedCoins` Coins currently in Account: -`CurrentCoins = OriginalCoins + ReceivedCoins - Delegated - Sent` +`CurrentCoins = OriginalVestingCoins + ReceivedCoins - Delegated - Sent` `CurrentCoins = vestingAccount.GetCoins()` **Maximum amount of coins spendable right now:** -`min( ReceivedCoins - SentCoins + OriginalCoins - LockedCoins, CurrentCoins )` +`min( ReceivedCoins - SentCoins + OriginalVestingCoins - LockedCoins, CurrentCoins )` From 187bc1972a73436ef0dcad2deaf8ae03a5206f6e Mon Sep 17 00:00:00 2001 From: Alessio Treglia <quadrispro@ubuntu.com> Date: Thu, 16 Aug 2018 22:47:59 +0200 Subject: [PATCH 55/97] Merge PR #1950: Validator.Owner -> .Operator * Rename --address-validator flag to --validator See #1901 * Update PENDING.md * Rename Validator.Owner -> Validator.Operator See #1901 --- PENDING.md | 3 + client/lcd/lcd_test.go | 31 +++++---- cmd/gaia/app/genesis.go | 4 +- cmd/gaia/cli_test/cli_test.go | 4 +- docs/sdk/clients.md | 10 +-- docs/spec/staking/transactions.md | 100 ++++++++++++++-------------- docs/validators/validator-setup.md | 12 +++- examples/democoin/mock/validator.go | 2 +- types/stake.go | 2 +- x/gov/tally.go | 4 +- x/slashing/app_test.go | 2 +- x/slashing/client/cli/flags.go | 2 +- x/stake/app_test.go | 4 +- x/stake/client/cli/flags.go | 2 +- x/stake/client/rest/query.go | 4 +- x/stake/handler_test.go | 10 +-- x/stake/keeper/_store.md | 18 ++--- x/stake/keeper/delegation.go | 10 +-- x/stake/keeper/slash.go | 8 +-- x/stake/keeper/validator.go | 38 +++++------ x/stake/keeper/validator_test.go | 38 +++++------ x/stake/types/validator.go | 40 +++++------ x/stake/types/validator_test.go | 8 +-- 23 files changed, 186 insertions(+), 170 deletions(-) diff --git a/PENDING.md b/PENDING.md index fc3c674f4..dafd653fe 100644 --- a/PENDING.md +++ b/PENDING.md @@ -40,6 +40,9 @@ BREAKING CHANGES * [cli] #1551: Officially removed `--name` from CLI commands * [cli] Genesis/key creation (`init`) now supports user-provided key passwords * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id +* [cli] \#1901 Flag --address-validator renamed to --validator in stake and slashing commands +* [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() +* [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface. FEATURES * [lcd] Can now query governance proposals by ProposalStatus diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index db584834a..09c0eddd1 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -361,13 +361,13 @@ func TestValidatorsQuery(t *testing.T) { validators := getValidators(t, port) require.Equal(t, len(validators), 1) - // make sure all the validators were found (order unknown because sorted by owner addr) + // make sure all the validators were found (order unknown because sorted by operator addr) foundVal := false pkBech := sdk.MustBech32ifyValPub(pks[0]) if validators[0].PubKey == pkBech { foundVal = true } - require.True(t, foundVal, "pkBech %v, owner %v", pkBech, validators[0].Owner) + require.True(t, foundVal, "pkBech %v, operator %v", pkBech, validators[0].Operator) } func TestValidatorQuery(t *testing.T) { @@ -375,9 +375,9 @@ func TestValidatorQuery(t *testing.T) { defer cleanup() require.Equal(t, 1, len(pks)) - validator1Owner := sdk.AccAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Owner) - assert.Equal(t, validator.Owner, validator1Owner, "The returned validator does not hold the correct data") + validator1Operator := sdk.AccAddress(pks[0].Address()) + validator := getValidator(t, port, validator1Operator) + assert.Equal(t, validator.Operator, validator1Operator, "The returned validator does not hold the correct data") } func TestBonding(t *testing.T) { @@ -386,10 +386,11 @@ func TestBonding(t *testing.T) { cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() - validator1Owner := sdk.AccAddress(pks[0].Address()) - validator := getValidator(t, port, validator1Owner) + validator1Operator := sdk.AccAddress(pks[0].Address()) + validator := getValidator(t, port, validator1Operator) - resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner, 60) + // create bond TX + resultTx := doDelegate(t, port, seed, name, password, addr, validator1Operator, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -400,7 +401,8 @@ func TestBonding(t *testing.T) { require.Equal(t, int64(40), coins.AmountOf(denom).Int64()) - bond := getDelegation(t, port, addr, validator1Owner) + // query validator + bond := getDelegation(t, port, addr, validator1Operator) require.Equal(t, "60.0000000000", bond.Shares) summary := getDelegationSummary(t, port, addr) @@ -411,16 +413,17 @@ func TestBonding(t *testing.T) { bondedValidators := getDelegatorValidators(t, port, addr) require.Len(t, bondedValidators, 1) - require.Equal(t, validator1Owner, bondedValidators[0].Owner) + require.Equal(t, validator1Operator, bondedValidators[0].Operator) require.Equal(t, validator.DelegatorShares.Add(sdk.NewDec(60)).String(), bondedValidators[0].DelegatorShares.String()) - bondedValidator := getDelegatorValidator(t, port, addr, validator1Owner) - require.Equal(t, validator1Owner, bondedValidator.Owner) + bondedValidator := getDelegatorValidator(t, port, addr, validator1Operator) + require.Equal(t, validator1Operator, bondedValidator.Operator) ////////////////////// // testing unbonding - resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner, 60) + // create unbond TX + resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Operator, 60) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -431,7 +434,7 @@ func TestBonding(t *testing.T) { coins = acc.GetCoins() require.Equal(t, int64(40), coins.AmountOf("steak").Int64()) - unbondings := getUndelegations(t, port, addr, validator1Owner) + unbondings := getUndelegations(t, port, addr, validator1Operator) require.Len(t, unbondings, 1, "Unbondings holds all unbonding-delegations") require.Equal(t, "60", unbondings[0].Balance.Amount.String()) diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index e35b21c4b..0399d6652 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -202,8 +202,8 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState // create the self-delegation from the issuedDelShares delegation := stake.Delegation{ - DelegatorAddr: validator.Owner, - ValidatorAddr: validator.Owner, + DelegatorAddr: validator.Operator, + ValidatorAddr: validator.Operator, Shares: issuedDelShares, Height: 0, } diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 244a9eb83..4f041d848 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -131,13 +131,13 @@ func TestGaiaCLICreateValidator(t *testing.T) { require.Equal(t, int64(8), barAcc.GetCoins().AmountOf("steak").Int64(), "%v", barAcc) validator := executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) - require.Equal(t, validator.Owner, barAddr) + require.Equal(t, validator.Operator, barAddr) require.True(sdk.DecEq(t, sdk.NewDec(2), validator.Tokens)) // unbond a single share unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags) unbondStr += fmt.Sprintf(" --from=%s", "bar") - unbondStr += fmt.Sprintf(" --address-validator=%s", barAddr) + unbondStr += fmt.Sprintf(" --validator=%s", barAddr) unbondStr += fmt.Sprintf(" --shares-amount=%v", "1") success := executeWrite(t, unbondStr, app.DefaultKeyPass) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 5d02548a2..17190d90a 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -120,9 +120,9 @@ On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond t ```bash gaiacli stake delegate \ --amount=10steak \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator=$(gaiad tendermint show-validator) \ --name=<key_name> \ - --chain-id=gaia-7005 + --chain-id=gaia-6002 ``` While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. @@ -137,9 +137,9 @@ If for any reason the validator misbehaves, or you want to unbond a certain amou ```bash gaiacli stake unbond begin \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator=$(gaiad tendermint show-validator) \ --shares=MAX \ - --name=<key_name> \ + --from=<key_name> \ --chain-id=gaia-7005 ``` @@ -152,7 +152,7 @@ gaiacli account <account_cosmosaccaddr> gaiacli stake delegation \ --address-delegator=<account_cosmosaccaddr> \ - --address-validator=$(gaiad tendermint show-validator) \ + --validator=$(gaiad tendermint show-validator) \ --chain-id=gaia-7005 ``` diff --git a/docs/spec/staking/transactions.md b/docs/spec/staking/transactions.md index d1b6a3626..ee2b976ae 100644 --- a/docs/spec/staking/transactions.md +++ b/docs/spec/staking/transactions.md @@ -1,7 +1,7 @@ ## Transaction Overview In this section we describe the processing of the transactions and the -corresponding updates to the state. Transactions: +corresponding updates to the state. Transactions: - TxCreateValidator - TxEditValidator - TxDelegation @@ -19,7 +19,7 @@ Other notes: - `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and modify objects from the store - `sdk.Dec` refers to a decimal type specified by the SDK. - + ### TxCreateValidator - triggers: `distribution.CreateValidatorDistribution` @@ -28,39 +28,39 @@ A validator is created using the `TxCreateValidator` transaction. ```golang type TxCreateValidator struct { - OwnerAddr sdk.Address + Operator sdk.Address ConsensusPubKey crypto.PubKey GovernancePubKey crypto.PubKey - SelfDelegation coin.Coin + SelfDelegation coin.Coin Description Description Commission sdk.Dec CommissionMax sdk.Dec CommissionMaxChange sdk.Dec } - + createValidator(tx TxCreateValidator): - validator = getValidator(tx.OwnerAddr) + validator = getValidator(tx.Operator) if validator != nil return // only one validator per address - - validator = NewValidator(OwnerAddr, ConsensusPubKey, GovernancePubKey, Description) + + validator = NewValidator(operatorAddr, ConsensusPubKey, GovernancePubKey, Description) init validator poolShares, delegatorShares set to 0 init validator commision fields from tx validator.PoolShares = 0 - + setValidator(validator) - - txDelegate = TxDelegate(tx.OwnerAddr, tx.OwnerAddr, tx.SelfDelegation) + + txDelegate = TxDelegate(tx.Operator, tx.Operator, tx.SelfDelegation) delegate(txDelegate, validator) // see delegate function in [TxDelegate](TxDelegate) return -``` +``` ### TxEditValidator If either the `Description` (excluding `DateBonded` which is constant), `Commission`, or the `GovernancePubKey` need to be updated, the -`TxEditCandidacy` transaction should be sent from the owner account: +`TxEditCandidacy` transaction should be sent from the operator account: ```golang type TxEditCandidacy struct { @@ -68,34 +68,34 @@ type TxEditCandidacy struct { Commission sdk.Dec Description Description } - + editCandidacy(tx TxEditCandidacy): validator = getValidator(tx.ValidatorAddr) - - if tx.Commission > CommissionMax || tx.Commission < 0 then fail + + if tx.Commission > CommissionMax || tx.Commission < 0 then fail if rateChange(tx.Commission) > CommissionMaxChange then fail validator.Commission = tx.Commission if tx.GovernancePubKey != nil validator.GovernancePubKey = tx.GovernancePubKey if tx.Description != nil validator.Description = tx.Description - + setValidator(store, validator) return ``` - + ### TxDelegate - + - triggers: `distribution.CreateOrModDelegationDistribution` Within this transaction the delegator provides coins, and in return receives some amount of their validator's delegator-shares that are assigned to -`Delegation.Shares`. +`Delegation.Shares`. ```golang type TxDelegate struct { - DelegatorAddr sdk.Address - ValidatorAddr sdk.Address - Amount sdk.Coin + DelegatorAddr sdk.Address + ValidatorAddr sdk.Address + Amount sdk.Coin } delegate(tx TxDelegate): @@ -104,14 +104,14 @@ delegate(tx TxDelegate): delegation = getDelegatorBond(DelegatorAddr, ValidatorAddr) if delegation == nil then delegation = NewDelegation(DelegatorAddr, ValidatorAddr) - + validator, pool, issuedDelegatorShares = validator.addTokensFromDel(tx.Amount, pool) delegation.Shares += issuedDelegatorShares - + setDelegation(delegation) updateValidator(validator) setPool(pool) - return + return ``` ### TxStartUnbonding @@ -120,28 +120,28 @@ Delegator unbonding is defined with the following transaction: ```golang type TxStartUnbonding struct { - DelegatorAddr sdk.Address - ValidatorAddr sdk.Address - Shares string + DelegatorAddr sdk.Address + ValidatorAddr sdk.Address + Shares string } -startUnbonding(tx TxStartUnbonding): +startUnbonding(tx TxStartUnbonding): delegation, found = getDelegatorBond(store, sender, tx.PubKey) - if !found == nil return - + if !found == nil return + if bond.Shares < tx.Shares return ErrNotEnoughBondShares validator, found = GetValidator(tx.ValidatorAddr) if !found { - return err + return err bond.Shares -= tx.Shares revokeCandidacy = false if bond.Shares.IsZero() { - if bond.DelegatorAddr == validator.Owner && validator.Revoked == false + if bond.DelegatorAddr == validator.Operator && validator.Revoked == false revokeCandidacy = true removeDelegation( bond) @@ -162,7 +162,7 @@ startUnbonding(tx TxStartUnbonding): validator = updateValidator(validator) if validator.DelegatorShares == 0 { - removeValidator(validator.Owner) + removeValidator(validator.Operator) return ``` @@ -185,7 +185,7 @@ redelegationComplete(tx TxRedelegate): returnTokens = ExpectedTokens * tx.startSlashRatio/validator.SlashRatio AddCoins(unbonding.DelegatorAddr, returnTokens) removeUnbondingDelegation(unbonding) - return + return ``` ### TxRedelegation @@ -206,20 +206,20 @@ type TxRedelegate struct { redelegate(tx TxRedelegate): pool = getPool() - delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Owner) + delegation = getDelegatorBond(tx.DelegatorAddr, tx.ValidatorFrom.Operator) if delegation == nil - return - - if delegation.Shares < tx.Shares - return + return + + if delegation.Shares < tx.Shares + return delegation.shares -= Tx.Shares validator, pool, createdCoins = validator.RemoveShares(pool, tx.Shares) setPool(pool) - - redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom, + + redelegation = newRedelegation(tx.DelegatorAddr, tx.validatorFrom, tx.validatorTo, tx.Shares, createdCoins, tx.CompletedTime) setRedelegation(redelegation) - return + return ``` ### TxCompleteRedelegation @@ -239,7 +239,7 @@ redelegationComplete(tx TxRedelegate): redelegation = getRedelegation(tx.DelegatorAddr, tx.validatorFrom, tx.validatorTo) if redelegation.CompleteTime >= CurrentBlockTime && redelegation.CompleteHeight >= CurrentBlockHeight removeRedelegation(redelegation) - return + return ``` ### Update Validators @@ -273,11 +273,11 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator) // use the validator provided because it has not yet been updated // in the main validator store - ownerAddr = iterator.Value() - if bytes.Equal(ownerAddr, newValidator.Owner) { + operatorAddr = iterator.Value() + if bytes.Equal(operatorAddr, newValidator.Operator) { validator = newValidator else - validator = getValidator(ownerAddr) + validator = getValidator(operatorAddr) // if not previously a validator (and unrevoked), // kick the cliff validator / bond this new validator @@ -285,7 +285,7 @@ updateBondedValidators(newValidator Validator) (updatedVal Validator) kickCliffValidator = true validator = bondValidator(ctx, store, validator) - if bytes.Equal(ownerAddr, newValidator.Owner) { + if bytes.Equal(operatorAddr, newValidator.Operator) { updatedVal = validator bondedValidatorsCount++ @@ -316,7 +316,7 @@ unbondValidator(ctx Context, store KVStore, validator Validator) } // perform all the store operations for when a validator status becomes bonded -bondValidator(ctx Context, store KVStore, validator Validator) Validator +bondValidator(ctx Context, store KVStore, validator Validator) Validator pool = GetPool(ctx) // set the status diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index dc3bf147f..1af796b37 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -31,8 +31,13 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau ```bash gaiacli stake create-validator \ --amount=5steak \ +<<<<<<< HEAD --pubkey=$(gaiad tendermint show-validator) \ --address-validator=<account_cosmosaccaddr> +======= + --pubkey=$(gaiad tendermint show_validator) \ + --validator=<account_cosmosaccaddr> +>>>>>>> 6f19f2ed... Rename --address-validator flag to --validator --moniker="choose a moniker" \ --chain-id=gaia-7005 \ --name=<key_name> @@ -46,7 +51,7 @@ The `--identity` can be used as to verify identity with systems like Keybase or ```bash gaiacli stake edit-validator - --address-validator=<account_cosmosaccaddr> + --validator=<account_cosmosaccaddr> --moniker="choose a moniker" \ --website="https://cosmos.network" \ --identity=6A0D65E29A4CBC8E @@ -61,8 +66,13 @@ View the validator's information with this command: ```bash gaiacli stake validator \ +<<<<<<< HEAD --address-validator=<account_cosmosaccaddr> \ --chain-id=gaia-7005 +======= + --validator=<account_cosmosaccaddr> \ + --chain-id=gaia-6002 +>>>>>>> 6f19f2ed... Rename --address-validator flag to --validator ``` ### Confirm Your Validator is Running diff --git a/examples/democoin/mock/validator.go b/examples/democoin/mock/validator.go index 789a1cb6a..f76f14803 100644 --- a/examples/democoin/mock/validator.go +++ b/examples/democoin/mock/validator.go @@ -19,7 +19,7 @@ func (v Validator) GetStatus() sdk.BondStatus { } // Implements sdk.Validator -func (v Validator) GetOwner() sdk.AccAddress { +func (v Validator) GetOperator() sdk.AccAddress { return v.Address } diff --git a/types/stake.go b/types/stake.go index acd24a154..ef7388f3b 100644 --- a/types/stake.go +++ b/types/stake.go @@ -40,7 +40,7 @@ type Validator interface { GetRevoked() bool // whether the validator is revoked GetMoniker() string // moniker of the validator GetStatus() BondStatus // status of the validator - GetOwner() AccAddress // owner AccAddress to receive/return validators coins + GetOperator() AccAddress // owner AccAddress to receive/return validators coins GetPubKey() crypto.PubKey // validation pubkey GetPower() Dec // validation power GetTokens() Dec // validation tokens diff --git a/x/gov/tally.go b/x/gov/tally.go index fc5b4317b..d8d4c7870 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -24,8 +24,8 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall currValidators := make(map[string]validatorGovInfo) keeper.vs.IterateValidatorsBonded(ctx, func(index int64, validator sdk.Validator) (stop bool) { - currValidators[validator.GetOwner().String()] = validatorGovInfo{ - Address: validator.GetOwner(), + currValidators[validator.GetOperator().String()] = validatorGovInfo{ + Address: validator.GetOperator(), Power: validator.GetPower(), DelegatorShares: validator.GetDelegatorShares(), Minus: sdk.ZeroDec(), diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 1e6a4e89d..e018c43e8 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -107,7 +107,7 @@ func TestSlashingMsgs(t *testing.T) { mapp.BeginBlock(abci.RequestBeginBlock{}) validator := checkValidator(t, mapp, stakeKeeper, addr1, true) - require.Equal(t, addr1, validator.Owner) + require.Equal(t, addr1, validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) unrevokeMsg := MsgUnrevoke{ValidatorAddr: sdk.AccAddress(validator.PubKey.Address())} diff --git a/x/slashing/client/cli/flags.go b/x/slashing/client/cli/flags.go index 43f8fa90a..09db8e825 100644 --- a/x/slashing/client/cli/flags.go +++ b/x/slashing/client/cli/flags.go @@ -2,5 +2,5 @@ package cli // nolint const ( - FlagAddressValidator = "address-validator" + FlagAddressValidator = "validator" ) diff --git a/x/stake/app_test.go b/x/stake/app_test.go index 9847ed290..65c64fdef 100644 --- a/x/stake/app_test.go +++ b/x/stake/app_test.go @@ -136,7 +136,7 @@ func TestStakeMsgs(t *testing.T) { mApp.BeginBlock(abci.RequestBeginBlock{}) validator := checkValidator(t, mApp, keeper, addr1, true) - require.Equal(t, addr1, validator.Owner) + require.Equal(t, addr1, validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.BondedTokens())) @@ -148,7 +148,7 @@ func TestStakeMsgs(t *testing.T) { mApp.BeginBlock(abci.RequestBeginBlock{}) validator = checkValidator(t, mApp, keeper, addr2, true) - require.Equal(t, addr2, validator.Owner) + require.Equal(t, addr2, validator.Operator) require.Equal(t, sdk.Bonded, validator.Status) require.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) diff --git a/x/stake/client/cli/flags.go b/x/stake/client/cli/flags.go index 3d5e90b35..d0e83ab3c 100644 --- a/x/stake/client/cli/flags.go +++ b/x/stake/client/cli/flags.go @@ -9,7 +9,7 @@ import ( // nolint const ( FlagAddressDelegator = "address-delegator" - FlagAddressValidator = "address-validator" + FlagAddressValidator = "validator" FlagAddressValidatorSrc = "addr-validator-source" FlagAddressValidatorDst = "addr-validator-dest" FlagPubKey = "pubkey" diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 4dfaa0f7f..036a3b451 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -114,7 +114,7 @@ func delegatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler } for _, validator := range validators { - validatorAddr = validator.Owner + validatorAddr = validator.Operator // Delegations delegations, statusCode, errMsg, err := getDelegatorDelegations(cliCtx, cdc, delegatorAddr, validatorAddr) @@ -400,7 +400,7 @@ func delegatorValidatorsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) ht for _, validator := range validators { // get all transactions from the delegator to val and append - validatorAccAddr = validator.Owner + validatorAccAddr = validator.Operator validator, statusCode, errMsg, errRes := getDelegatorValidator(cliCtx, cdc, delegatorAddr, validatorAccAddr) if errRes != nil { diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index a06be0f88..9ff72090e 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -136,13 +136,13 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, addr1, validator.Owner) + assert.Equal(t, addr1, validator.Operator) assert.Equal(t, pk1, validator.PubKey) assert.Equal(t, sdk.NewDec(10), validator.BondedTokens()) assert.Equal(t, sdk.NewDec(10), validator.DelegatorShares) assert.Equal(t, Description{}, validator.Description) - // two validators can't have the same owner address + // two validators can't have the same operator address msgCreateValidator2 := newTestMsgCreateValidator(addr1, pk2, 10) got = handleMsgCreateValidator(ctx, msgCreateValidator2, keeper) require.False(t, got.IsOK(), "%v", got) @@ -152,7 +152,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { got = handleMsgCreateValidator(ctx, msgCreateValidator3, keeper) require.False(t, got.IsOK(), "%v", got) - // must have different pubkey and owner + // must have different pubkey and operator msgCreateValidator4 := newTestMsgCreateValidator(addr2, pk2, 10) got = handleMsgCreateValidator(ctx, msgCreateValidator4, keeper) require.True(t, got.IsOK(), "%v", got) @@ -160,7 +160,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, addr2, validator.Owner) + assert.Equal(t, addr2, validator.Operator) assert.Equal(t, pk2, validator.PubKey) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) @@ -180,7 +180,7 @@ func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) { require.True(t, found) assert.Equal(t, sdk.Bonded, validator.Status) - assert.Equal(t, validatorAddr, validator.Owner) + assert.Equal(t, validatorAddr, validator.Operator) assert.Equal(t, pk, validator.PubKey) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.Tokens)) assert.True(sdk.DecEq(t, sdk.NewDec(10), validator.DelegatorShares)) diff --git a/x/stake/keeper/_store.md b/x/stake/keeper/_store.md index 1c95ffe87..818b17ac0 100644 --- a/x/stake/keeper/_store.md +++ b/x/stake/keeper/_store.md @@ -4,18 +4,18 @@ This document provided a bit more insight as to the purpose of several related prefixed areas of the staking store which are accessed in `x/stake/keeper.go`. -## Validators +## Validators - Prefix Key Space: ValidatorsKey - - Key/Sort: Validator Owner Address + - Key/Sort: Validator Operator Address - Value: Validator Object - Contains: All Validator records independent of being bonded or not - - Used For: Retrieve validator from owner address, general validator retrieval + - Used For: Retrieve validator from operator address, general validator retrieval ## Validators By Power - Prefix Key Space: ValidatorsByPowerKey - Key/Sort: Validator Power (equivalent bonded shares) then Block Height then Transaction Order - - Value: Validator Owner Address + - Value: Validator Operator Address - Contains: All Validator records independent of being bonded or not - Used For: Determining who the top validators are whom should be bonded @@ -26,19 +26,19 @@ prefixed areas of the staking store which are accessed in `x/stake/keeper.go`. - Contains: The cliff validator (ex. 100th validator) power - Used For: Efficient updates to validator status -## Validators Bonded +## Validators Bonded - Prefix Key Space: ValidatorsBondedKey - Key/Sort: Validator PubKey Address (NOTE same as Tendermint) - - Value: Validator Owner Address + - Value: Validator Operator Address - Contains: Only currently bonded Validators - - Used For: Retrieving the list of all currently bonded validators when updating - for a new validator entering the validator set we may want to loop + - Used For: Retrieving the list of all currently bonded validators when updating + for a new validator entering the validator set we may want to loop through this set to determine who we've kicked out. retrieving validator by tendermint index ## Tendermint Updates - Prefix Key Space: TendermintUpdatesKey - - Key/Sort: Validator Owner Address + - Key/Sort: Validator Operator Address - Value: Tendermint ABCI Validator - Contains: Validators are queued to affect the consensus validation set in Tendermint - Used For: Informing Tendermint of the validator set updates, is used only intra-block, as the diff --git a/x/stake/keeper/delegation.go b/x/stake/keeper/delegation.go index 4b4d267aa..4256df4b5 100644 --- a/x/stake/keeper/delegation.go +++ b/x/stake/keeper/delegation.go @@ -221,11 +221,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delegatorAddr sdk.AccAddress, bondAmt validator types.Validator, subtractAccount bool) (newShares sdk.Dec, err sdk.Error) { // Get or create the delegator delegation - delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Owner) + delegation, found := k.GetDelegation(ctx, delegatorAddr, validator.Operator) if !found { delegation = types.Delegation{ DelegatorAddr: delegatorAddr, - ValidatorAddr: validator.Owner, + ValidatorAddr: validator.Operator, Shares: sdk.ZeroDec(), } } @@ -282,9 +282,9 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr // remove the delegation if delegation.Shares.IsZero() { - // if the delegation is the owner of the validator then + // if the delegation is the operator of the validator then // trigger a revoke validator - if bytes.Equal(delegation.DelegatorAddr, validator.Owner) && validator.Revoked == false { + if bytes.Equal(delegation.DelegatorAddr, validator.Operator) && validator.Revoked == false { validator.Revoked = true } k.RemoveDelegation(ctx, delegation) @@ -303,7 +303,7 @@ func (k Keeper) unbond(ctx sdk.Context, delegatorAddr, validatorAddr sdk.AccAddr // update then remove validator if necessary validator = k.UpdateValidator(ctx, validator) if validator.DelegatorShares.IsZero() { - k.RemoveValidator(ctx, validator.Owner) + k.RemoveValidator(ctx, validator.Operator) } return diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index c1fabe441..471886c26 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -43,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in pubkey.Address())) return } - ownerAddress := validator.GetOwner() + operatorAddress := validator.GetOperator() // Track remaining slash amount for the validator // This will decrease when we slash unbondings and @@ -68,7 +68,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in case infractionHeight < ctx.BlockHeight(): // Iterate through unbonding delegations from slashed validator - unbondingDelegations := k.GetUnbondingDelegationsFromValidator(ctx, ownerAddress) + unbondingDelegations := k.GetUnbondingDelegationsFromValidator(ctx, operatorAddress) for _, unbondingDelegation := range unbondingDelegations { amountSlashed := k.slashUnbondingDelegation(ctx, unbondingDelegation, infractionHeight, slashFactor) if amountSlashed.IsZero() { @@ -78,7 +78,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } // Iterate through redelegations from slashed validator - redelegations := k.GetRedelegationsFromValidator(ctx, ownerAddress) + redelegations := k.GetRedelegationsFromValidator(ctx, operatorAddress) for _, redelegation := range redelegations { amountSlashed := k.slashRedelegation(ctx, validator, redelegation, infractionHeight, slashFactor) if amountSlashed.IsZero() { @@ -103,7 +103,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in validator = k.UpdateValidator(ctx, validator) // remove validator if it has been reduced to zero shares if validator.Tokens.IsZero() { - k.RemoveValidator(ctx, validator.Owner) + k.RemoveValidator(ctx, validator.Operator) } // Log that a slash occurred! diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index ce5a19061..5f880ebab 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -36,25 +36,25 @@ func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (val func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) bz := types.MustMarshalValidator(k.cdc, validator) - store.Set(GetValidatorKey(validator.Owner), bz) + store.Set(GetValidatorKey(validator.Operator), bz) } // validator index func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Owner) + store.Set(GetValidatorByPubKeyIndexKey(validator.PubKey), validator.Operator) } // validator index func (k Keeper) SetValidatorByPowerIndex(ctx sdk.Context, validator types.Validator, pool types.Pool) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.Owner) + store.Set(GetValidatorsByPowerIndexKey(validator, pool), validator.Operator) } // validator index func (k Keeper) SetValidatorBondedIndex(ctx sdk.Context, validator types.Validator) { store := ctx.KVStore(k.storeKey) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) + store.Set(GetValidatorsBondedIndexKey(validator.Operator), []byte{}) } // used in testing @@ -203,7 +203,7 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) { func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator { store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) - oldValidator, oldFound := k.GetValidator(ctx, validator.Owner) + oldValidator, oldFound := k.GetValidator(ctx, validator.Operator) validator = k.updateForRevoking(ctx, oldFound, oldValidator, validator) powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator) @@ -220,11 +220,11 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type (oldFound && oldValidator.Status == sdk.Bonded): bz := k.cdc.MustMarshalBinary(validator.ABCIValidator()) - store.Set(GetTendermintUpdatesKey(validator.Owner), bz) + store.Set(GetTendermintUpdatesKey(validator.Operator), bz) if cliffPower != nil { cliffAddr := sdk.AccAddress(k.GetCliffValidator(ctx)) - if bytes.Equal(cliffAddr, validator.Owner) { + if bytes.Equal(cliffAddr, validator.Operator) { k.updateCliffValidator(ctx, validator) } } @@ -255,7 +255,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type // if decreased in power but still bonded, update Tendermint validator if oldFound && oldValidator.BondedTokens().GT(validator.BondedTokens()) { bz := k.cdc.MustMarshalBinary(validator.ABCIValidator()) - store.Set(GetTendermintUpdatesKey(validator.Owner), bz) + store.Set(GetTendermintUpdatesKey(validator.Operator), bz) } } @@ -307,7 +307,7 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato panic("failed to create valid validator power iterator") } - if bytes.Equal(affectedVal.Owner, newCliffVal.Owner) { + if bytes.Equal(affectedVal.Operator, newCliffVal.Operator) { // The affected validator remains the cliff validator, however, since // the store does not contain the new power, set the new cliff // validator to the affected validator. @@ -365,7 +365,7 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } valPower = GetValidatorsByPowerIndexKey(newValidator, pool) - store.Set(valPower, newValidator.Owner) + store.Set(valPower, newValidator.Operator) return valPower } @@ -407,7 +407,7 @@ func (k Keeper) UpdateBondedValidators( // situation that this is the "affected validator" just use the // validator provided because it has not yet been updated in the store ownerAddr := iterator.Value() - if bytes.Equal(ownerAddr, affectedValidator.Owner) { + if bytes.Equal(ownerAddr, affectedValidator.Operator) { validator = affectedValidator } else { var found bool @@ -462,7 +462,7 @@ func (k Keeper) UpdateBondedValidators( // bond the new validator validator = k.bondValidator(ctx, validatorToBond) - if bytes.Equal(validator.Owner, affectedValidator.Owner) { + if bytes.Equal(validator.Operator, affectedValidator.Operator) { return validator, true } } @@ -572,10 +572,10 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) - store.Set(GetTendermintUpdatesKey(validator.Owner), bzABCI) + store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI) // also remove from the Bonded types.Validators Store - store.Delete(GetValidatorsBondedIndexKey(validator.Owner)) + store.Delete(GetValidatorsBondedIndexKey(validator.Operator)) return validator } @@ -596,11 +596,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // save the now bonded validator record to the three referenced stores k.SetValidator(ctx, validator) - store.Set(GetValidatorsBondedIndexKey(validator.Owner), []byte{}) + store.Set(GetValidatorsBondedIndexKey(validator.Operator), []byte{}) // add to accumulated changes for tendermint bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator()) - store.Set(GetTendermintUpdatesKey(validator.Owner), bzABCI) + store.Set(GetTendermintUpdatesKey(validator.Operator), bzABCI) return validator } @@ -623,10 +623,10 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.AccAddress) { // delete from the current and power weighted validator groups if the validator // is bonded - and add validator with zero power to the validator updates - if store.Get(GetValidatorsBondedIndexKey(validator.Owner)) == nil { + if store.Get(GetValidatorsBondedIndexKey(validator.Operator)) == nil { return } - store.Delete(GetValidatorsBondedIndexKey(validator.Owner)) + store.Delete(GetValidatorsBondedIndexKey(validator.Operator)) bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero()) store.Set(GetTendermintUpdatesKey(address), bz) @@ -651,7 +651,7 @@ func (k Keeper) setCliffValidator(ctx sdk.Context, validator types.Validator, po store := ctx.KVStore(k.storeKey) bz := GetValidatorsByPowerIndexKey(validator, pool) store.Set(ValidatorPowerCliffKey, bz) - store.Set(ValidatorCliffIndexKey, validator.Owner) + store.Set(ValidatorCliffIndexKey, validator.Operator) } // clear the current validator and power of the validator on the cliff diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 7b15a9c7f..7f17b391b 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -128,7 +128,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert new cliff validator to be set to the second lowest bonded validator by power newCliffVal := validators[numVals-maxVals+1] - require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -141,7 +141,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert cliff validator has not change but increased in power cliffPower = keeper.GetCliffValidatorPower(ctx) - require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) } @@ -240,7 +240,7 @@ func TestValidatorBasics(t *testing.T) { assert.True(ValEq(t, validators[2], resVals[2])) // remove a record - keeper.RemoveValidator(ctx, validators[1].Owner) + keeper.RemoveValidator(ctx, validators[1].Operator) _, found = keeper.GetValidator(ctx, addrVals[1]) require.False(t, found) } @@ -269,11 +269,11 @@ func GetValidatorSortingUnmixed(t *testing.T) { assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators) - assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) - assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) - assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) - assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators) - assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators) + assert.Equal(t, validators[3].Operator, resValidators[0].Operator, "%v", resValidators) + assert.Equal(t, validators[4].Operator, resValidators[1].Operator, "%v", resValidators) + assert.Equal(t, validators[1].Operator, resValidators[2].Operator, "%v", resValidators) + assert.Equal(t, validators[2].Operator, resValidators[3].Operator, "%v", resValidators) + assert.Equal(t, validators[0].Operator, resValidators[4].Operator, "%v", resValidators) // test a basic increase in voting power validators[3].Tokens = sdk.NewDec(500) @@ -380,11 +380,11 @@ func GetValidatorSortingMixed(t *testing.T) { assert.Equal(t, sdk.NewDec(100), resValidators[2].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(1), resValidators[3].BondedTokens(), "%v", resValidators) assert.Equal(t, sdk.NewDec(0), resValidators[4].BondedTokens(), "%v", resValidators) - assert.Equal(t, validators[3].Owner, resValidators[0].Owner, "%v", resValidators) - assert.Equal(t, validators[4].Owner, resValidators[1].Owner, "%v", resValidators) - assert.Equal(t, validators[1].Owner, resValidators[2].Owner, "%v", resValidators) - assert.Equal(t, validators[2].Owner, resValidators[3].Owner, "%v", resValidators) - assert.Equal(t, validators[0].Owner, resValidators[4].Owner, "%v", resValidators) + assert.Equal(t, validators[3].Operator, resValidators[0].Operator, "%v", resValidators) + assert.Equal(t, validators[4].Operator, resValidators[1].Operator, "%v", resValidators) + assert.Equal(t, validators[1].Operator, resValidators[2].Operator, "%v", resValidators) + assert.Equal(t, validators[2].Operator, resValidators[3].Operator, "%v", resValidators) + assert.Equal(t, validators[0].Operator, resValidators[4].Operator, "%v", resValidators) } // TODO separate out into multiple tests @@ -409,7 +409,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { validators[i] = keeper.UpdateValidator(ctx, validators[i]) } for i := range amts { - validators[i], found = keeper.GetValidator(ctx, validators[i].Owner) + validators[i], found = keeper.GetValidator(ctx, validators[i].Operator) require.True(t, found) } resValidators := keeper.GetValidatorsByPower(ctx) @@ -433,7 +433,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { // validator 3 enters bonded validator set ctx = ctx.WithBlockHeight(40) - validators[3], found = keeper.GetValidator(ctx, validators[3].Owner) + validators[3], found = keeper.GetValidator(ctx, validators[3].Operator) require.True(t, found) validators[3], pool, _ = validators[3].AddTokensFromDel(pool, 1) keeper.SetPool(ctx, pool) @@ -460,7 +460,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { require.Equal(t, nMax, uint16(len(resValidators))) assert.True(ValEq(t, validators[0], resValidators[0])) assert.True(ValEq(t, validators[2], resValidators[1])) - validator, exists := keeper.GetValidator(ctx, validators[3].Owner) + validator, exists := keeper.GetValidator(ctx, validators[3].Operator) require.Equal(t, exists, true) require.Equal(t, int64(40), validator.BondHeight) } @@ -530,7 +530,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { } for i := range amts { var found bool - validators[i], found = keeper.GetValidator(ctx, validators[i].Owner) + validators[i], found = keeper.GetValidator(ctx, validators[i].Operator) require.True(t, found) } assert.Equal(t, sdk.Unbonded, validators[0].Status) @@ -603,8 +603,8 @@ func TestGetTendermintUpdatesAllNone(t *testing.T) { keeper.ClearTendermintUpdates(ctx) require.Equal(t, 0, len(keeper.GetTendermintUpdates(ctx))) - keeper.RemoveValidator(ctx, validators[0].Owner) - keeper.RemoveValidator(ctx, validators[1].Owner) + keeper.RemoveValidator(ctx, validators[0].Operator) + keeper.RemoveValidator(ctx, validators[1].Operator) updates = keeper.GetTendermintUpdates(ctx) assert.Equal(t, 2, len(updates)) diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index bd7d76993..7f40c57f5 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -20,9 +20,9 @@ import ( // exchange rate. Voting power can be calculated as total bonds multiplied by // exchange rate. type Validator struct { - Owner sdk.AccAddress `json:"owner"` // sender of BondTx - UnbondTx returns here - PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator - Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? + Operator sdk.AccAddress `json:"operator"` // sender of BondTx - UnbondTx returns here + PubKey crypto.PubKey `json:"pub_key"` // pubkey of validator + Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -43,9 +43,9 @@ type Validator struct { } // NewValidator - initialize a new validator -func NewValidator(owner sdk.AccAddress, pubKey crypto.PubKey, description Description) Validator { +func NewValidator(operator sdk.AccAddress, pubKey crypto.PubKey, description Description) Validator { return Validator{ - Owner: owner, + Operator: operator, PubKey: pubKey, Revoked: false, Status: sdk.Unbonded, @@ -103,8 +103,8 @@ func MustMarshalValidator(cdc *wire.Codec, validator Validator) []byte { } // unmarshal a redelegation from a store key and value -func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator { - validator, err := UnmarshalValidator(cdc, ownerAddr, value) +func MustUnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) Validator { + validator, err := UnmarshalValidator(cdc, operatorAddr, value) if err != nil { panic(err) } @@ -113,8 +113,8 @@ func MustUnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) Validator } // unmarshal a redelegation from a store key and value -func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Validator, err error) { - if len(ownerAddr) != sdk.AddrLen { +func UnmarshalValidator(cdc *wire.Codec, operatorAddr, value []byte) (validator Validator, err error) { + if len(operatorAddr) != sdk.AddrLen { err = fmt.Errorf("%v", ErrBadValidatorAddr(DefaultCodespace).Data()) return } @@ -125,7 +125,7 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Val } return Validator{ - Owner: ownerAddr, + Operator: operatorAddr, PubKey: storeValue.PubKey, Revoked: storeValue.Revoked, Tokens: storeValue.Tokens, @@ -144,7 +144,7 @@ func UnmarshalValidator(cdc *wire.Codec, ownerAddr, value []byte) (validator Val } // HumanReadableString returns a human readable string representation of a -// validator. An error is returned if the owner or the owner's public key +// validator. An error is returned if the operator or the operator's public key // cannot be converted to Bech32 format. func (v Validator) HumanReadableString() (string, error) { bechVal, err := sdk.Bech32ifyValPub(v.PubKey) @@ -153,7 +153,7 @@ func (v Validator) HumanReadableString() (string, error) { } resp := "Validator \n" - resp += fmt.Sprintf("Owner: %s\n", v.Owner) + resp += fmt.Sprintf("Operator: %s\n", v.Operator) resp += fmt.Sprintf("Validator: %s\n", bechVal) resp += fmt.Sprintf("Revoked: %v\n", v.Revoked) resp += fmt.Sprintf("Status: %s\n", sdk.BondStatusToString(v.Status)) @@ -175,9 +175,9 @@ func (v Validator) HumanReadableString() (string, error) { // validator struct for bech output type BechValidator struct { - Owner sdk.AccAddress `json:"owner"` // in bech32 - PubKey string `json:"pub_key"` // in bech32 - Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? + Operator sdk.AccAddress `json:"operator"` // in bech32 + PubKey string `json:"pub_key"` // in bech32 + Revoked bool `json:"revoked"` // has the validator been revoked from bonded status? Status sdk.BondStatus `json:"status"` // validator status (bonded/unbonding/unbonded) Tokens sdk.Dec `json:"tokens"` // delegated tokens (incl. self-delegation) @@ -205,9 +205,9 @@ func (v Validator) Bech32Validator() (BechValidator, error) { } return BechValidator{ - Owner: v.Owner, - PubKey: bechValPubkey, - Revoked: v.Revoked, + Operator: v.Operator, + PubKey: bechValPubkey, + Revoked: v.Revoked, Status: v.Status, Tokens: v.Tokens, @@ -233,7 +233,7 @@ func (v Validator) Bech32Validator() (BechValidator, error) { // nolint gocyclo - why dis fail? func (v Validator) Equal(c2 Validator) bool { return v.PubKey.Equals(c2.PubKey) && - bytes.Equal(v.Owner, c2.Owner) && + bytes.Equal(v.Operator, c2.Operator) && v.Status.Equal(c2.Status) && v.Tokens.Equal(c2.Tokens) && v.DelegatorShares.Equal(c2.DelegatorShares) && @@ -430,7 +430,7 @@ var _ sdk.Validator = Validator{} func (v Validator) GetRevoked() bool { return v.Revoked } func (v Validator) GetMoniker() string { return v.Description.Moniker } func (v Validator) GetStatus() sdk.BondStatus { return v.Status } -func (v Validator) GetOwner() sdk.AccAddress { return v.Owner } +func (v Validator) GetOperator() sdk.AccAddress { return v.Operator } func (v Validator) GetPubKey() crypto.PubKey { return v.PubKey } func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() } func (v Validator) GetTokens() sdk.Dec { return v.Tokens } diff --git a/x/stake/types/validator_test.go b/x/stake/types/validator_test.go index 3981f5754..f4c874057 100644 --- a/x/stake/types/validator_test.go +++ b/x/stake/types/validator_test.go @@ -72,7 +72,7 @@ func TestABCIValidatorZero(t *testing.T) { func TestRemoveTokens(t *testing.T) { validator := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: sdk.NewDec(100), @@ -148,7 +148,7 @@ func TestAddTokensValidatorUnbonded(t *testing.T) { // TODO refactor to make simpler like the AddToken tests above func TestRemoveDelShares(t *testing.T) { valA := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: sdk.NewDec(100), @@ -176,7 +176,7 @@ func TestRemoveDelShares(t *testing.T) { poolTokens := sdk.NewDec(5102) delShares := sdk.NewDec(115) validator := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: poolTokens, @@ -229,7 +229,7 @@ func TestPossibleOverflow(t *testing.T) { poolTokens := sdk.NewDec(2159) delShares := sdk.NewDec(391432570689183511).Quo(sdk.NewDec(40113011844664)) validator := Validator{ - Owner: addr1, + Operator: addr1, PubKey: pk1, Status: sdk.Bonded, Tokens: poolTokens, From bce09055b2b66f4ba6c81d6e1bc67d7f27793beb Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Fri, 17 Aug 2018 05:56:15 +0900 Subject: [PATCH 56/97] Merge PR #2058: comment fix An outdated comment fixed to be less confusing. --- examples/basecoin/types/account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basecoin/types/account.go b/examples/basecoin/types/account.go index 671494311..45774ae43 100644 --- a/examples/basecoin/types/account.go +++ b/examples/basecoin/types/account.go @@ -10,7 +10,7 @@ var _ auth.Account = (*AppAccount)(nil) // AppAccount is a custom extension for this application. It is an example of // extending auth.BaseAccount with custom fields. It is compatible with the -// stock auth.AccountStore, since auth.AccountStore uses the flexible go-amino +// stock auth.AccountMapper, since auth.AccountMapper uses the flexible go-amino // library. type AppAccount struct { auth.BaseAccount From 8bb79d12ca0d905f34d734e59479cfba5e6775d1 Mon Sep 17 00:00:00 2001 From: Dev Ojha <ValarDragon@users.noreply.github.com> Date: Thu, 16 Aug 2018 14:45:07 -0700 Subject: [PATCH 57/97] Fix non-deterministic map iteration in fuzzer (#2069) * This demonstrates that the state machine is non-deterministic if there are more than two txs in a block. * fix non-deterministic map iteration * (squash this) fix build errors * (squash this) iterate using range --- cmd/gaia/app/sim_test.go | 40 ++++++++++++--------- x/bank/simulation/sim_test.go | 1 + x/gov/simulation/sim_test.go | 1 + x/mock/simulation/random_simulate_blocks.go | 25 ++++++++++--- x/stake/simulation/sim_test.go | 1 + 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 5d0edcba2..3b85a89cf 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -130,17 +130,13 @@ func TestFullGaiaSimulation(t *testing.T) { }, numBlocks, blockSize, + false, ) } -// TODO: Make this not depend on Gaia or any of the modules, -// and place it in random_simulation_test.go -// -// Test doesn't use `app.ExportAppStateAndValidators` as that panics with the following: -// panic: Stored pool should not have been nil [recovered] -// panic: Stored pool should not have been nil -// Change to `app.ExportAppStateAndValidators` once it is fixed +// TODO: Make another test for the fuzzer itself, which just has noOp txs +// and doesn't depend on gaia func TestAppStateDeterminism(t *testing.T) { numTimesToRun := 5 appHashList := make([]json.RawMessage, numTimesToRun) @@ -152,27 +148,39 @@ func TestAppStateDeterminism(t *testing.T) { app := NewGaiaApp(logger, db, nil) noOpInvariant := func(t *testing.T, baseapp *baseapp.BaseApp, log string) {} - noOpTestAndRunTx := func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, - privKeys []crypto.PrivKey, log string, event func(string), - ) (action string, err sdk.Error) { - return "", nil - } + // noOpTestAndRunTx := func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + // privKeys []crypto.PrivKey, log string, event func(string), + // ) (action string, err sdk.Error) { + // return "", nil + // } // Run randomized simulation simulation.SimulateFromSeed( t, app.BaseApp, appStateFn, seed, []simulation.TestAndRunTx{ - noOpTestAndRunTx, + banksim.TestAndRunSingleInputMsgSend(app.accountMapper), + govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), + stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgEditValidator(app.stakeKeeper), + stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), + stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), }, []simulation.RandSetup{}, []simulation.Invariant{noOpInvariant}, - 0, - 10, + 20, + 20, + true, ) appHash := app.LastCommitID().Hash appHashList[i] = appHash } for i := 1; i < numTimesToRun; i++ { - require.Equal(t, appHashList[0], appHashList[i]) + require.Equal(t, appHashList[0], appHashList[i], "appHashes: %v", appHashList) } } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 49e3dfa92..8fedeca79 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -42,5 +42,6 @@ func TestBankWithRandomMessages(t *testing.T) { TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, 30, 30, + false, ) } diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index e7131f8fc..691aa1cd2 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -64,5 +64,6 @@ func TestGovWithRandomMessages(t *testing.T) { }, []simulation.Invariant{ AllInvariants(), }, 10, 100, + false, ) } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 1b6953631..ffc00500e 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "math/rand" + "sort" "testing" "time" @@ -20,17 +21,17 @@ import ( // Simulate tests application by sending random messages. func Simulate( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numBlocks int, blockSize int, + invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit) } // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numBlocks int, blockSize int, + invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) fmt.Printf("%s\n", log) @@ -104,6 +105,9 @@ func SimulateFromSeed( } res := app.EndBlock(abci.RequestEndBlock{}) + if commit { + app.Commit() + } header.Height++ header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) @@ -123,6 +127,17 @@ func SimulateFromSeed( DisplayEvents(events) } +func getKeys(validators map[string]mockValidator) []string { + keys := make([]string, len(validators)) + i := 0 + for key := range validators { + keys[i] = key + i++ + } + sort.Strings(keys) + return keys +} + // RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock { @@ -131,7 +146,9 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m } signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 - for _, mVal := range validators { + + for _, key := range getKeys(validators) { + mVal := validators[key] mVal.livenessState = livenessTransitions.NextState(r, mVal.livenessState) signed := true diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 3e80e1eb3..84745cd1d 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -57,5 +57,6 @@ func TestStakeWithRandomMessages(t *testing.T) { }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), }, 10, 100, + false, ) } From b8cfc1e19fe2f11c33917cb062bbf0477a18b80c Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Fri, 17 Aug 2018 16:19:33 +0200 Subject: [PATCH 58/97] Merge PR #2068: Minor simulation changes --- .circleci/config.yml | 19 +++ Makefile | 10 +- cmd/gaia/app/sim_test.go | 129 ++++++++++---------- x/gov/handler.go | 6 +- x/mock/simulation/random_simulate_blocks.go | 7 +- x/stake/simulation/invariants.go | 11 +- 6 files changed, 103 insertions(+), 79 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3be6151e9..116bdc866 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,6 +101,22 @@ jobs: export PATH="$GOBIN:$PATH" make test_sim_modules + test_sim_gaia_nondeterminism: + <<: *defaults + parallelism: 1 + steps: + - attach_workspace: + at: /tmp/workspace + - restore_cache: + key: v1-pkg-cache + - restore_cache: + key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - run: + name: Test individual module simulations + command: | + export PATH="$GOBIN:$PATH" + make test_sim_gaia_nondeterminism + test_sim_gaia_fast: <<: *defaults parallelism: 1 @@ -202,6 +218,9 @@ workflows: - test_sim_modules: requires: - setup_dependencies + - test_sim_gaia_nondeterminism: + requires: + - setup_dependencies - test_sim_gaia_fast: requires: - setup_dependencies diff --git a/Makefile b/Makefile index 655d8574e..5a8dd82fe 100644 --- a/Makefile +++ b/Makefile @@ -134,12 +134,16 @@ test_sim_modules: @echo "Running individual module simulations..." @go test $(PACKAGES_SIMTEST) +test_sim_gaia_nondeterminism: + @echo "Running nondeterminism test..." + @go test ./cmd/gaia/app -run TestAppStateDeterminism -SimulationEnabled=true -v -timeout 10m + test_sim_gaia_fast: - @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -v -timeout 24h + @echo "Running quick Gaia simulation. This may take several minutes..." + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 24h test_sim_gaia_slow: - @echo "Running full Gaia simulation. This may take several minutes..." + @echo "Running full Gaia simulation. This may take awhile!" @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h test_cover: diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 3b85a89cf..8a81a1a92 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -3,6 +3,7 @@ package app import ( "encoding/json" "flag" + "fmt" "math/rand" "testing" @@ -84,6 +85,34 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json return appState } +func testAndRunTxs(app *GaiaApp) []simulation.TestAndRunTx { + return []simulation.TestAndRunTx{ + banksim.TestAndRunSingleInputMsgSend(app.accountMapper), + govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), + stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgEditValidator(app.stakeKeeper), + stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), + stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), + } +} + +func invariants(app *GaiaApp) []simulation.Invariant { + return []simulation.Invariant{ + func(t *testing.T, baseapp *baseapp.BaseApp, log string) { + banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) + govsim.AllInvariants()(t, baseapp, log) + stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) + slashingsim.AllInvariants()(t, baseapp, log) + }, + } +} + func TestFullGaiaSimulation(t *testing.T) { if !enabled { t.Skip("Skipping Gaia simulation") @@ -100,34 +129,12 @@ func TestFullGaiaSimulation(t *testing.T) { app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) - allInvariants := func(t *testing.T, baseapp *baseapp.BaseApp, log string) { - banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) - govsim.AllInvariants()(t, baseapp, log) - stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) - slashingsim.AllInvariants()(t, baseapp, log) - } - // Run randomized simulation simulation.SimulateFromSeed( t, app.BaseApp, appStateFn, seed, - []simulation.TestAndRunTx{ - banksim.TestAndRunSingleInputMsgSend(app.accountMapper), - govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), - stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgEditValidator(app.stakeKeeper), - stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), - stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), - slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), - }, + testAndRunTxs(app), []simulation.RandSetup{}, - []simulation.Invariant{ - allInvariants, - }, + invariants(app), numBlocks, blockSize, false, @@ -138,49 +145,37 @@ func TestFullGaiaSimulation(t *testing.T) { // TODO: Make another test for the fuzzer itself, which just has noOp txs // and doesn't depend on gaia func TestAppStateDeterminism(t *testing.T) { - numTimesToRun := 5 - appHashList := make([]json.RawMessage, numTimesToRun) - - seed := rand.Int63() - for i := 0; i < numTimesToRun; i++ { - logger := log.NewNopLogger() - db := dbm.NewMemDB() - app := NewGaiaApp(logger, db, nil) - - noOpInvariant := func(t *testing.T, baseapp *baseapp.BaseApp, log string) {} - // noOpTestAndRunTx := func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, - // privKeys []crypto.PrivKey, log string, event func(string), - // ) (action string, err sdk.Error) { - // return "", nil - // } - - // Run randomized simulation - simulation.SimulateFromSeed( - t, app.BaseApp, appStateFn, seed, - []simulation.TestAndRunTx{ - banksim.TestAndRunSingleInputMsgSend(app.accountMapper), - govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), - govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), - stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgEditValidator(app.stakeKeeper), - stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), - stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), - slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), - }, - []simulation.RandSetup{}, - []simulation.Invariant{noOpInvariant}, - 20, - 20, - true, - ) - appHash := app.LastCommitID().Hash - appHashList[i] = appHash + if !enabled { + t.Skip("Skipping Gaia simulation") } - for i := 1; i < numTimesToRun; i++ { - require.Equal(t, appHashList[0], appHashList[i], "appHashes: %v", appHashList) + + numSeeds := 5 + numTimesToRunPerSeed := 5 + appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + + for i := 0; i < numSeeds; i++ { + seed := rand.Int63() + for j := 0; j < numTimesToRunPerSeed; j++ { + logger := log.NewNopLogger() + db := dbm.NewMemDB() + app := NewGaiaApp(logger, db, nil) + + // Run randomized simulation + simulation.SimulateFromSeed( + t, app.BaseApp, appStateFn, seed, + testAndRunTxs(app), + []simulation.RandSetup{}, + []simulation.Invariant{}, + 20, + 20, + true, + ) + appHash := app.LastCommitID().Hash + fmt.Printf(">>> APP HASH: %v, %X\n", appHash, appHash) + appHashList[j] = appHash + } + for k := 1; k < numTimesToRunPerSeed; k++ { + require.Equal(t, appHashList[0], appHashList[k]) + } } } diff --git a/x/gov/handler.go b/x/gov/handler.go index 554c06a8a..d1de0cbab 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -1,6 +1,8 @@ package gov import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov/tags" ) @@ -152,8 +154,8 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) - logger.Info("Validator %s failed to vote on proposal %d, slashing", - val.GetOwner(), activeProposal.GetProposalID()) + logger.Info(fmt.Sprintf("Validator %s failed to vote on proposal %d, slashing", + val.GetOwner(), activeProposal.GetProposalID())) } resTags.AppendTag(tags.Action, action) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index ffc00500e..c7e616614 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -105,9 +105,6 @@ func SimulateFromSeed( } res := app.EndBlock(abci.RequestEndBlock{}) - if commit { - app.Commit() - } header.Height++ header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) @@ -116,6 +113,10 @@ func SimulateFromSeed( // Make sure invariants hold at end of block AssertAllInvariants(t, app, invariants, log) + if commit { + app.Commit() + } + // Generate a random RequestBeginBlock with the current validator set for the next block request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) diff --git a/x/stake/simulation/invariants.go b/x/stake/simulation/invariants.go index e4869693c..96e7931c7 100644 --- a/x/stake/simulation/invariants.go +++ b/x/stake/simulation/invariants.go @@ -28,7 +28,7 @@ func AllInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simula func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { ctx := app.NewContext(false, abci.Header{}) - pool := k.GetPool(ctx) + //pool := k.GetPool(ctx) loose := sdk.ZeroInt() bonded := sdk.ZeroRat() @@ -52,11 +52,14 @@ func SupplyInvariants(ck bank.Keeper, k stake.Keeper, am auth.AccountMapper) sim }) // Loose tokens should equal coin supply plus unbonding delegations plus tokens on unbonded validators - require.True(t, pool.LooseTokens.RoundInt64() == loose.Int64(), "expected loose tokens to equal total steak held by accounts - pool.LooseTokens: %v, sum of account tokens: %v\nlog: %s", - pool.LooseTokens.RoundInt64(), loose.Int64(), log) + // XXX TODO https://github.com/cosmos/cosmos-sdk/issues/2063#issuecomment-413720872 + // require.True(t, pool.LooseTokens.RoundInt64() == loose.Int64(), "expected loose tokens to equal total steak held by accounts - pool.LooseTokens: %v, sum of account tokens: %v\nlog: %s", + // pool.LooseTokens.RoundInt64(), loose.Int64(), log) // Bonded tokens should equal sum of tokens with bonded validators - require.True(t, pool.BondedTokens.Equal(bonded), "expected bonded tokens to equal total steak held by bonded validators\nlog: %s", log) + // XXX TODO https://github.com/cosmos/cosmos-sdk/issues/2063#issuecomment-413720872 + // require.True(t, pool.BondedTokens.RoundInt64() == bonded.RoundInt64(), "expected bonded tokens to equal total steak held by bonded validators - pool.BondedTokens: %v, sum of bonded validator tokens: %v\nlog: %s", + // pool.BondedTokens.RoundInt64(), bonded.RoundInt64(), log) // TODO Inflation check on total supply } From cf03076a0a65f7989087579ce362b44439941875 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Fri, 17 Aug 2018 11:33:13 -0400 Subject: [PATCH 59/97] Merge PR #2047: Fix Invalid Cliff Validator Power Comparison --- CHANGELOG.md | 1 + x/stake/keeper/validator.go | 19 +++++++++---------- x/stake/keeper/validator_test.go | 14 +++++++++++++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55104830b..7ec3d6658 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,7 @@ BUG FIXES - [x/stake] \#2021 Fixed repeated CLI commands in staking * Gaia + - [x/stake] [#2077](https://github.com/cosmos/cosmos-sdk/pull/2077) Fixed invalid cliff power comparison - \#1804 Fixes gen-tx genesis generation logic temporarily until upstream updates - \#1799 Fix `gaiad export` - \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 8b8cea73d..debb91729 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -280,10 +280,6 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato panic(fmt.Sprintf("cliff validator record not found for address: %v\n", cliffAddr)) } - // NOTE: We get the power via affectedVal since the store (by power key) - // has yet to be updated. - affectedValPower := affectedVal.GetPower() - // Create a validator iterator ranging from smallest to largest by power // starting the current cliff validator's power. start := GetValidatorsByPowerIndexKey(oldCliffVal, pool) @@ -307,16 +303,19 @@ func (k Keeper) updateCliffValidator(ctx sdk.Context, affectedVal types.Validato panic("failed to create valid validator power iterator") } + affectedValRank := GetValidatorsByPowerIndexKey(affectedVal, pool) + newCliffValRank := GetValidatorsByPowerIndexKey(newCliffVal, pool) + if bytes.Equal(affectedVal.Owner, newCliffVal.Owner) { // The affected validator remains the cliff validator, however, since - // the store does not contain the new power, set the new cliff - // validator to the affected validator. - bz := GetValidatorsByPowerIndexKey(affectedVal, pool) - store.Set(ValidatorPowerCliffKey, bz) - } else if affectedValPower.GT(newCliffVal.GetPower()) { + // the store does not contain the new power, update the new power rank. + store.Set(ValidatorPowerCliffKey, affectedValRank) + } else if bytes.Compare(affectedValRank, newCliffValRank) > 0 { // The affected validator no longer remains the cliff validator as it's - // power is greater than the new current cliff validator. + // power is greater than the new cliff validator. k.setCliffValidator(ctx, newCliffVal, pool) + } else { + panic("invariant broken: the cliff validator should change or it should remain the same") } } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index b9e61a101..3446f0dc8 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -48,7 +48,6 @@ func TestSetValidator(t *testing.T) { updates := keeper.GetTendermintUpdates(ctx) require.Equal(t, 1, len(updates)) require.Equal(t, validator.ABCIValidator(), updates[0]) - } func TestUpdateValidatorByPowerIndex(t *testing.T) { @@ -143,6 +142,19 @@ func TestCliffValidatorChange(t *testing.T) { cliffPower = keeper.GetCliffValidatorPower(ctx) require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) + + // add enough power to cliff validator to be equal in rank to next validator + newCliffVal, pool, _ = newCliffVal.AddTokensFromDel(pool, 9) + keeper.SetPool(ctx, pool) + newCliffVal = keeper.UpdateValidator(ctx, newCliffVal) + + // assert new cliff validator due to power rank construction + newCliffVal = validators[numVals-maxVals+2] + require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + + // assert cliff validator power should have been updated + cliffPower = keeper.GetCliffValidatorPower(ctx) + require.Equal(t, GetValidatorsByPowerIndexKey(newCliffVal, pool), cliffPower) } func TestSlashToZeroPowerRemoved(t *testing.T) { From 466e0c04d598358d93071dfb5a893935e786a972 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Fri, 17 Aug 2018 18:49:57 +0200 Subject: [PATCH 60/97] R4R: Update cli docs (#2076) * Update cli docs, fixes #2026 * Fixed merge conflicts * Updated chain_id --- docs/sdk/clients.md | 245 +++++++++++++++++++++++++---- docs/validators/validator-setup.md | 161 +++---------------- 2 files changed, 240 insertions(+), 166 deletions(-) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 914a6c599..846cc3b2a 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -12,27 +12,25 @@ `gaiacli` is the command line interface to manage accounts and transactions on Cosmos testnets. Here is a list of useful `gaiacli` commands, including usage examples. -### Key Types +### Keys + +#### Key Types There are three types of key representations that are used: - `cosmosaccaddr` - - Derived from account keys generated by `gaiacli keys add` - Used to receive funds - e.g. `cosmosaccaddr15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc` - - `cosmosaccpub` - - Derived from account keys generated by `gaiacli keys add` - e.g. `cosmosaccpub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm` - - `cosmosvalpub` - Generated when the node is created with `gaiad init`. - Get this value with `gaiad tendermint show_validator` - e.g. `cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c` -### Generate Keys +#### Generate Keys You'll need an account private and public key pair \(a.k.a. `sk, pk` respectively\) to be able to receive funds, send txs, bond tx, etc. @@ -66,10 +64,14 @@ gaiad tendermint show_validator We strongly recommend _NOT_ using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds. ::: -### Get Tokens +### Account + +#### Get Tokens The best way to get tokens is from the [Cosmos Testnet Faucet](https://faucetcosmos.network). If the faucet is not working for you, try asking [#cosmos-validators](https://riot.im/app/#/room/#cosmos-validators:matrix.org). The faucet needs the `cosmosaccaddr` from the account you wish to use for staking. +#### Query Account balance + After receiving tokens to your address, you can view your account's balance by typing: ```bash @@ -79,7 +81,6 @@ gaiacli account <account_cosmosaccaddr> ::: warning Note When you query an account balance with zero tokens, you will get this error: `No account with address <account_cosmosaccaddr> was found in the state.` This can also happen if you fund the account before your node has fully synced with the chain. These are both normal. -We're working on improving our error messages! ::: ### Send Tokens @@ -87,7 +88,7 @@ We're working on improving our error messages! ```bash gaiacli send \ --amount=10faucetToken \ - --chain-id=gaia-7005 \ + --chain-id=<chain_id> \ --name=<key_name> \ --to=<destination_cosmosaccaddr> ``` @@ -109,20 +110,40 @@ You can also check your balance at a given block by using the `--block` flag: gaiacli account <account_cosmosaccaddr> --block=<block_height> ``` -### Delegate +### Staking + +#### Set up a Validator + +Please refer to the [Validator Setup](https://cosmos.network/docs/validators/validator-setup.html) section for a more complete guide on how to set up a validator-candidate. + +#### Delegate to a Validator On the upcoming mainnet, you can delegate `atom` to a validator. These [delegators](/resources/delegators-faq) can receive part of the validator's fee revenue. Read more about the [Cosmos Token Model](https://github.com/cosmos/cosmos/raw/master/Cosmos_Token_Model.pdf). -### Bond Tokens +##### Query Validators -On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond tokens to a testnet validator: +You can query the list of all validators of a specific chain: + +```bash +gaiacli stake validators +``` + +If you want to get the information of a single validator you can check it with: + +```bash +gaiacli stake validator <account_cosmosaccaddr> +``` + +#### Bond Tokens + +On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond tokens to a testnet validator (*i.e.* delegate): ```bash gaiacli stake delegate \ --amount=10steak \ --address-validator=$(gaiad tendermint show_validator) \ --name=<key_name> \ - --chain-id=gaia-7005 + --chain-id=<chain_id> ``` While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. @@ -131,33 +152,197 @@ While tokens are bonded, they are pooled with all the other bonded tokens in the Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://faucetcosmos.network/)! ::: -### Unbond Tokens +##### Query Delegations -If for any reason the validator misbehaves, or you want to unbond a certain amount of tokens, use this following command. You can unbond a specific amount of`shares`\(eg:`12.1`\) or all of them \(`MAX`\). +Once submitted a delegation to a validator, you can see it's information by using the following command: + +```bash +gaiacli stake delegation \ + --address-delegator=<account_cosmosaccaddr> \ + --address-validator=$(gaiad tendermint show-validator) +``` + +Or if you want to check all your current delegations with disctinct validators: + +```bash +gaiacli stake delegations <account_cosmosaccaddr> +``` + +You can also get previous delegation(s) status by adding the `--height` flag. + +#### Unbond Tokens + +If for any reason the validator misbehaves, or you just want to unbond a certain amount of tokens, use this following command. You can unbond a specific `shares-amount` (eg:`12.1`\) or a `shares-percent` (eg:`25`) with the corresponding flags. ```bash gaiacli stake unbond begin \ - --address-validator=$(gaiad tendermint show_validator) \ - --shares=MAX \ - --name=<key_name> \ - --chain-id=gaia-7005 + --address-validator=$(gaiad tendermint show-validator) \ + --shares-percent=100 \ + --from=<key_name> \ + --chain-id=<chain_id> ``` -Later you must use the `gaiacli stake unbond complete` command to finish -unbonding at which point you can can check your balance and your stake -delegation to see that the unbonding went through successfully. +Later you must complete the unbonding process by using the `gaiacli stake unbond complete` command: ```bash -gaiacli account <account_cosmosaccaddr> - -gaiacli stake delegation \ - --address-delegator=<account_cosmosaccaddr> \ - --address-validator=$(gaiad tendermint show_validator) \ - --chain-id=gaia-7005 +gaiacli stake unbond complete \ + --address-validator=$(gaiad tendermint show-validator) \ + --from=<key_name> \ + --chain-id=<chain_id> ``` -## Light Client Daemon +##### Query Unbonding-Delegations + +Once you begin an unbonding-delegation, you can see it's information by using the following command: + +```bash +gaiacli stake unbonding-delegation \ + --address-delegator=<account_cosmosaccaddr> \ + --address-validator=$(gaiad tendermint show-validator) \ +``` + +Or if you want to check all your current unbonding-delegations with disctinct validators: + +```bash +gaiacli stake unbonding-delegations <account_cosmosaccaddr> +``` + +You can also get previous unbonding-delegation(s) status by adding the `--height` flag. + +#### Redelegate Tokens + +A redelegation is a type delegation that allows you to bond illiquid tokens from one validator to another: + +```bash +gaiacli stake redelegate begin \ + --address-validator-source=$(gaiad tendermint show-validator) \ + --address-validator-dest=<account_cosmosaccaddr> \ + --shares-percent=50 \ + --from=<key_name> \ + --chain-id=<chain_id> +``` + +Here you can also redelegate a specific `shares-amount` or a `shares-percent` with the corresponding flags. + +Later you must complete the redelegation process by using the `gaiacli stake redelegate complete` command: + +```bash +gaiacli stake unbond complete \ + --address-validator=$(gaiad tendermint show-validator) \ + --from=<key_name> \ + --chain-id=<chain_id> +``` + +##### Query Redelegations + +Once you begin an redelegation, you can see it's information by using the following command: + +```bash +gaiacli stake redelegation \ + --address-delegator=<account_cosmosaccaddr> \ + --address-validator-source=$(gaiad tendermint show-validator) \ + --address-validator-dest=<account_cosmosaccaddr> \ +``` + +Or if you want to check all your current unbonding-delegations with disctinct validators: + +```bash +gaiacli stake redelegations <account_cosmosaccaddr> +``` + +You can also get previous redelegation(s) status by adding the `--height` flag. + +### Governance + +Governance is the process from which users in the Cosmos Hub can come to consensus on software upgrades, parameters of the mainnet or on custom text proposals. This is done through voting on proposals, which will be submitted by `Atom` holders on the mainnet. + +Some considerations about the voting process: + +- Voting is done by bonded `Atom` holders on a 1 bonded `Atom` 1 vote basis +- Delegators inherit the vote of their validator if they don't vote +- **Validators MUST vote on every proposal**. If a validator does not vote on a proposal, they will be **partially slashed** +- Votes are tallied at the end of the voting period (2 weeks on mainnet). Each address can vote multiple times to update its `Option` value (paying the transaction fee each time), only the last casted vote will count as valid +- Voters can choose between options `Yes`, `No`, `NoWithVeto` and `Abstain` + At the end of the voting period, a proposal is accepted if `(YesVotes/(YesVotes+NoVotes+NoWithVetoVotes))>1/2` and `(NoWithVetoVotes/(YesVotes+NoVotes+NoWithVetoVotes))<1/3`. It is rejected otherwise + +For more information about the governance process and how it works, please check out the Governance module [specification](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/governance). + +#### Create a Governance proposal + +In order to create a governance proposal, you must submit an initial deposit along with the proposal details: + +- `title`: Title of the proposal +- `description`: Description of the proposal +- `type`: Type of proposal. Must be of value _Text_ (types _SoftwareUpgrade_ and _ParameterChange_ not supported yet). + +```bash +gaiacli gov submit-proposal \ + --title=<title> \ + --description=<description> \ + --type=<Text/ParameterChange/SoftwareUpgrade> \ + --proposer=<account_cosmosaccaddr> \ + --deposit=<40steak> \ + --from=<name> \ + --chain-id=<chain_id> +``` + +##### Query proposals + +Once created, you can now query information of the proposal: + +```bash +gaiacli gov query-proposal \ + --proposal-id=<proposal_id> +``` + +Or query all available proposals: + +```bash +gaiacli gov query-proposals +``` + +You can also query proposals filtered by `voter` or `depositer` by using the corresponding flags. + +#### Increase deposit + +In order for a proposal to be broadcasted to the network, the amount deposited must be above a `minDeposit` value (default: `10 steak`). If the proposal you previously created didn't meet this requirement, you can still increase the total amount deposited to activate it. Once the minimum deposit is reached, the proposal enters voting period: + +```bash +gaiacli gov deposit \ + --proposal-id=<proposal_id> \ + --depositer=<account_cosmosaccaddr> \ + --deposit=<200steak> \ + --from=<name> \ + --chain-id=<chain_id> +``` + +> _NOTE_: Proposals that don't meet this requirement will be deleted after `MaxDepositPeriod` is reached. + +#### Vote on a proposal + +After a proposal's deposit reaches the `MinDeposit` value, the voting period opens. Bonded `Atom` holders can then cast vote on it: + +```bash +gaiacli gov vote \ + --proposal-id=<proposal_id> \ + --voter=<account_cosmosaccaddr> \ + --option=<Yes/No/NoWithVeto/Abstain> \ + --from=<name> \ + --chain-id=<chain_id> +``` + +##### Query vote + +Check the vote with the option you just submitted: + +```bash +gaiacli gov query-vote \ + --proposal-id=<proposal_id> \ + --voter=<account_cosmosaccaddr> +``` + +## Gaia-Lite ::: tip Note -🚧Documentation coming soon! +🚧 We are actively working on documentation for Gaia-lite. ::: diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 837471bf2..f6ca97a15 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -1,7 +1,7 @@ # Validator Setup ::: warning Current Testnet -The current testnet is `gaia-7005`. +The current testnet is `gaia-8000`. ::: Before setting up your validator node, make sure you've already gone through the [Full Node Setup](/getting-started/full-node.md) guide. @@ -34,7 +34,7 @@ gaiacli stake create-validator \ --pubkey=$(gaiad tendermint show_validator) \ --address-validator=<account_cosmosaccaddr> --moniker="choose a moniker" \ - --chain-id=gaia-7005 \ + --chain-id=<chain_id> \ --name=<key_name> ``` @@ -51,7 +51,7 @@ gaiacli stake edit-validator --website="https://cosmos.network" \ --identity=6A0D65E29A4CBC8E --details="To infinity and beyond!" - --chain-id=gaia-7005 \ + --chain-id=<chain_id> \ --name=<key_name> ``` @@ -62,7 +62,26 @@ View the validator's information with this command: ```bash gaiacli stake validator \ --address-validator=<account_cosmosaccaddr> \ - --chain-id=gaia-7005 + --chain-id=<chain_id> +``` + +### Track Validator Signing Information + +In order to keep track of a validator's signatures in the past you can do so by using the `signing-info` command: + +```bash +gaiacli stake signing-information <validator-pubkey>\ + --chain-id=<chain_id> +``` + +### Unrevoke Validator + +When a validator is `Revoked` for downtime, you must submit an `Unrevoke` transaction in order to be able to get block proposer rewards again (depends on the zone fee distribution). + +```bash +gaiacli stake unrevoke \ + --from=<key_name> \ + --chain-id=<chain_id> ``` ### Confirm Your Validator is Running @@ -75,7 +94,6 @@ gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show_valida You should also be able to see your validator on the [Explorer](https://explorecosmos.network/validators). You are looking for the `bech32` encoded `address` in the `~/.gaiad/config/priv_validator.json` file. - ::: warning Note To be in the validator set, you need to have more total voting power than the 100th validator. ::: @@ -84,7 +102,7 @@ To be in the validator set, you need to have more total voting power than the 10 ### Problem #1: My validator has `voting_power: 0` -Your validator has become auto-unbonded. In `gaia-7005`, we unbond validators if they do not vote on `50` of the last `100` blocks. Since blocks are proposed every ~2 seconds, a validator unresponsive for ~100 seconds will become unbonded. This usually happens when your `gaiad` process crashes. +Your validator has become auto-unbonded. In `gaia-8000`, we unbond validators if they do not vote on `50` of the last `100` blocks. Since blocks are proposed every ~2 seconds, a validator unresponsive for ~100 seconds will become unbonded. This usually happens when your `gaiad` process crashes. Here's how you can return the voting power back to your validator. First, if `gaiad` is not running, start it up again: @@ -95,7 +113,7 @@ gaiad start Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmosaccaddr>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`. ```bash -gaiacli stake unrevoke <cosmosaccaddr> --chain-id=gaia-7005 --name=<name> +gaiacli stake unrevoke <cosmosaccaddr> --chain-id=<chain_id> --name=<name> ``` ::: danger Warning @@ -132,132 +150,3 @@ LimitNOFILE=4096 [Install] WantedBy=multi-user.target ``` - -## Delegating to a Validator - -On the upcoming mainnet, you can delegate `Atom` to a validator. These [delegators](https://cosmos.network/resources/delegators) can receive part of the validator's fee revenue. Read more about the [Cosmos Token Model](https://github.com/cosmos/cosmos/raw/master/Cosmos_Token_Model.pdf). - -### Bond Tokens - -On the testnet, we delegate `steak` instead of `Atom`. Here's how you can bond tokens to a testnet validator: - -```bash -gaiacli stake delegate \ - --amount=10steak \ - --address-delegator=<account_cosmosaccaddr> \ - --address-validator=<validator_cosmosaccaddr> \ - --from=<key_name> \ - --chain-id=gaia-7001 -``` - -While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool. - -> _*NOTE:*_ Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://gaia.faucetcosmos.network/)! - -### Unbond Tokens - -If for any reason the validator misbehaves, or you want to unbond a certain amount of tokens, use this following command. You can unbond a specific amount of`shares`\(eg:`12.1`\) or all of them \(`MAX`\). - -```bash -gaiacli stake unbond \ - --address-delegator=<account_cosmosaccaddr> \ - --address-validator=<validator_cosmosaccaddr> \ - --shares=MAX \ - --from=<key_name> \ - --chain-id=gaia-7001 -``` - -You can check your balance and your stake delegation to see that the unbonding went through successfully. - -```bash -gaiacli account <account_cosmosaccaddr> - -gaiacli stake delegation \ - --address-delegator=<account_cosmosaccaddr> \ - --address-validator=<validator_cosmosaccaddr> \ - --chain-id=gaia-7001 -``` - -## Governance - -Governance is the process from which users in the Cosmos Hub can come to consensus on software upgrades, parameters of the mainnet or on custom text proposals. This is done through voting on proposals, which will be submitted by `Atom` holders on the mainnet. - -Some considerations about the voting process: - -- Voting is done by bonded `Atom` holders on a 1 bonded `Atom` 1 vote basis -- Delegators inherit the vote of their validator if they don't vote -- **Validators MUST vote on every proposal**. If a validator does not vote on a proposal, they will be **partially slashed** -- Votes are tallied at the end of the voting period (2 weeks on mainnet). Each address can vote multiple times to update its `Option` value (paying the transaction fee each time), only the last casted vote will count as valid -- Voters can choose between options `Yes`, `No`, `NoWithVeto` and `Abstain` -At the end of the voting period, a proposal is accepted if `(YesVotes/(YesVotes+NoVotes+NoWithVetoVotes))>1/2` and `(NoWithVetoVotes/(YesVotes+NoVotes+NoWithVetoVotes))<1/3`. It is rejected otherwise - -For more information about the governance process and how it works, please check out the Governance module [specification](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/governance). - -### Create a Governance proposal - -In order to create a governance proposal, you must submit an initial deposit along with the proposal details: - -- `title`: Title of the proposal -- `description`: Description of the proposal -- `type`: Type of proposal. Must be of value _Text_ (types _SoftwareUpgrade_ and _ParameterChange_ not supported yet). - -```bash -gaiacli gov submit-proposal \ - --title=<title> \ - --description=<description> \ - --type=<Text/ParameterChange/SoftwareUpgrade> \ - --proposer=<account_cosmosaccaddr> \ - --deposit=<40steak> \ - --from=<name> \ - --chain-id=gaia-7001 -``` - - -### Increase deposit - -In order for a proposal to be broadcasted to the network, the amount deposited must be above a `minDeposit` value (default: `10 steak`). If the proposal you previously created didn't meet this requirement, you can still increase the total amount deposited to activate it. Once the minimum deposit is reached, the proposal enters voting period: - -```bash -gaiacli gov deposit \ - --proposalID=<proposal_id> \ - --depositer=<account_cosmosaccaddr> \ - --deposit=<200steak> \ - --from=<name> \ - --chain-id=gaia-7001 -``` - -> _NOTE_: Proposals that don't meet this requirement will be deleted after `MaxDepositPeriod` is reached. - -#### Query proposal - -Once created, you can now query information of the proposal: - -```bash -gaiacli gov query-proposal \ - --proposalID=<proposal_id> \ - --chain-id=gaia-7001 -``` - -### Vote on a proposal - -After a proposal's deposit reaches the `MinDeposit` value, the voting period opens. Bonded `Atom` holders can then cast vote on it: - -```bash -gaiacli gov vote \ - --proposalID=<proposal_id> \ - --voter=<account_cosmosaccaddr> \ - --option=<Yes/No/NoWithVeto/Abstain> \ - --from=<name> \ - --chain-id=gaia-7001 -``` - -#### Query vote - -Check the vote with the option you just submitted: - -```bash -gaiacli gov query-vote \ - --proposalID=<proposal_id> \ - --voter=<account_cosmosaccaddr> \ - --chain-id=gaia-7001 -``` From 5794f3c3cefc70f83b038440d32f11ae55871f07 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Sat, 18 Aug 2018 07:41:12 -0400 Subject: [PATCH 61/97] Merge PR #2083: Fix broken invariant of bonded validator power decrease --- CHANGELOG.md | 2 +- x/stake/keeper/validator.go | 16 ++++++-- x/stake/keeper/validator_test.go | 67 +++++++++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec3d6658..f6b91607a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,7 +112,7 @@ BUG FIXES - [tests] \#1551 Fixed invalid LCD test JSON payload in `doIBCTransfer` - [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) - [x/gov] \#1757 Fix VoteOption conversion to String - + * [x/stake] [#2083] Fix broken invariant of bonded validator power decrease ## 0.23.1 diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index debb91729..8105e3747 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -452,21 +452,29 @@ func (k Keeper) UpdateBondedValidators( // swap the cliff validator for a new validator if the affected validator // was bonded if newValidatorBonded { - // unbond the cliff validator if oldCliffValidatorAddr != nil { - cliffVal, found := k.GetValidator(ctx, oldCliffValidatorAddr) + oldCliffVal, found := k.GetValidator(ctx, oldCliffValidatorAddr) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr)) } - k.unbondValidator(ctx, cliffVal) + if bytes.Equal(validatorToBond.Owner, affectedValidator.Owner) { + // unbond the old cliff validator iff the affected validator was + // newly bonded and has greater power + k.unbondValidator(ctx, oldCliffVal) + } else { + // otherwise unbond the affected validator, which must have been + // kicked out + affectedValidator = k.unbondValidator(ctx, affectedValidator) + } } - // bond the new validator validator = k.bondValidator(ctx, validatorToBond) if bytes.Equal(validator.Owner, affectedValidator.Owner) { return validator, true } + + return affectedValidator, true } return types.Validator{}, false diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 3446f0dc8..62f9823a9 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -88,6 +88,69 @@ func TestUpdateValidatorByPowerIndex(t *testing.T) { require.True(t, keeper.validatorByPowerIndexExists(ctx, power)) } +func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { + numVals := 10 + maxVals := 5 + + // create context, keeper, and pool for tests + ctx, _, keeper := CreateTestInput(t, false, 0) + pool := keeper.GetPool(ctx) + + // create keeper parameters + params := keeper.GetParams(ctx) + params.MaxValidators = uint16(maxVals) + keeper.SetParams(ctx, params) + + // create a random pool + pool.LooseTokens = sdk.NewRat(10000) + pool.BondedTokens = sdk.NewRat(1234) + keeper.SetPool(ctx, pool) + + validators := make([]types.Validator, numVals) + for i := 0; i < len(validators); i++ { + moniker := fmt.Sprintf("val#%d", int64(i)) + val := types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) + val.BondHeight = int64(i) + val.BondIntraTxCounter = int16(i) + val, pool, _ = val.AddTokensFromDel(pool, int64((i+1)*10)) + + keeper.SetPool(ctx, pool) + val = keeper.UpdateValidator(ctx, val) + validators[i] = val + } + + nextCliffVal := validators[numVals-maxVals+1] + + // remove enough tokens to kick out the validator below the current cliff + // validator and next in line cliff validator + nextCliffVal, pool, _ = nextCliffVal.RemoveDelShares(pool, sdk.NewRat(21)) + keeper.SetPool(ctx, pool) + nextCliffVal = keeper.UpdateValidator(ctx, nextCliffVal) + + // require the cliff validator has changed + cliffVal := validators[numVals-maxVals-1] + require.Equal(t, cliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + + // require the cliff validator power has changed + cliffPower := keeper.GetCliffValidatorPower(ctx) + require.Equal(t, GetValidatorsByPowerIndexKey(cliffVal, pool), cliffPower) + + expectedValStatus := map[int]sdk.BondStatus{ + 9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded, + 0: sdk.Unbonded, 1: sdk.Unbonded, 2: sdk.Unbonded, 3: sdk.Unbonded, 6: sdk.Unbonded, + } + + // require all the validators have their respective statuses + for valIdx, status := range expectedValStatus { + valAddr := validators[valIdx].Owner + val, _ := keeper.GetValidator(ctx, valAddr) + + require.Equal( + t, val.GetStatus(), status, + fmt.Sprintf("expected validator to have status: %s", sdk.BondStatusToString(status))) + } +} + func TestCliffValidatorChange(t *testing.T) { numVals := 10 maxVals := 5 @@ -415,11 +478,13 @@ func TestGetValidatorsEdgeCases(t *testing.T) { var validators [4]types.Validator for i, amt := range amts { pool := keeper.GetPool(ctx) - validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{}) + moniker := fmt.Sprintf("val#%d", int64(i)) + validators[i] = types.NewValidator(Addrs[i], PKs[i], types.Description{Moniker: moniker}) validators[i], pool, _ = validators[i].AddTokensFromDel(pool, amt) keeper.SetPool(ctx, pool) validators[i] = keeper.UpdateValidator(ctx, validators[i]) } + for i := range amts { validators[i], found = keeper.GetValidator(ctx, validators[i].Owner) require.True(t, found) From 8747eaac7df4c962d2b4fc35d7926de83463eca5 Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Mon, 20 Aug 2018 11:22:46 +0900 Subject: [PATCH 62/97] A URL to abci-spec.md fixed /docs/abci-spec.md -> /docs/app-dev/abci-spec.md --- docs/sdk/core/app4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk/core/app4.md b/docs/sdk/core/app4.md index 0724e5e7a..b6596ef0c 100644 --- a/docs/sdk/core/app4.md +++ b/docs/sdk/core/app4.md @@ -16,7 +16,7 @@ here we will introduce the other ABCI requests sent by Tendermint, and how we can use them to build more advanced applications. For a more complete depiction of the ABCI and how its used, see [the -specification](https://github.com/tendermint/tendermint/blob/master/docs/abci-spec.md) +specification](https://github.com/tendermint/tendermint/blob/master/docs/app-dev/abci-spec.md) ## InitChain From 459f126e9b1afd6ec2968b269564ab9b2c6ed9f2 Mon Sep 17 00:00:00 2001 From: Max Levy <35595512+maxim-levy@users.noreply.github.com> Date: Mon, 20 Aug 2018 11:29:03 +0900 Subject: [PATCH 63/97] The URL to abci-spec.md fixed docs/abci-spec.md -> docs/app-dev/abci-spec.md --- docs/sdk/core/app1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk/core/app1.md b/docs/sdk/core/app1.md index 54121d05b..a2978ffb0 100644 --- a/docs/sdk/core/app1.md +++ b/docs/sdk/core/app1.md @@ -469,7 +469,7 @@ Tendermint consensus engine. It would be initialized by a Genesis file, and it would be driven by blocks of transactions committed by the underlying Tendermint consensus. We'll talk more about ABCI and how this all works a bit later, but feel free to check the -[specification](https://github.com/tendermint/tendermint/blob/master/docs/abci-spec.md). +[specification](https://github.com/tendermint/tendermint/blob/master/docs/app-dev/abci-spec.md). We'll also see how to connect our app to a complete suite of components for running and using a live blockchain application. From 87ca812b0bebe16392d37c91fae04b7b9b2c88df Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Mon, 20 Aug 2018 12:47:04 +0200 Subject: [PATCH 64/97] Correctly read/write governance state --- cmd/gaia/app/app.go | 3 ++- cmd/gaia/app/genesis.go | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 9b318c8b1..eba5f8605 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -185,7 +185,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci // load the address to pubkey map slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.StakeData) - gov.InitGenesis(ctx, app.govKeeper, gov.DefaultGenesisState()) + gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) return abci.ResponseInitChain{ Validators: validators, @@ -208,6 +208,7 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val genState := GenesisState{ Accounts: accounts, StakeData: stake.WriteGenesis(ctx, app.stakeKeeper), + GovData: gov.WriteGenesis(ctx, app.govKeeper), } appState, err = wire.MarshalJSONIndent(app.cdc, genState) if err != nil { diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 0399d6652..24b160a51 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -11,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/stake" "github.com/spf13/pflag" @@ -32,6 +33,7 @@ var ( type GenesisState struct { Accounts []GenesisAccount `json:"accounts"` StakeData stake.GenesisState `json:"stake"` + GovData gov.GenesisState `json:"gov"` } // GenesisAccount doesn't need pubkey or sequence @@ -216,6 +218,7 @@ func GaiaAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (genesisState genesisState = GenesisState{ Accounts: genaccs, StakeData: stakeData, + GovData: gov.DefaultGenesisState(), } return } From 98a5844310d94310f47c689385f5a03d696b8b62 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Mon, 20 Aug 2018 17:06:18 +0200 Subject: [PATCH 65/97] Makefile phony; Gopkg.lock --- Gopkg.lock | 14 +++++++------- Makefile | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 14e88f8b8..38830c49e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -48,12 +48,12 @@ revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] - digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] pruneopts = "UT" - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" [[projects]] digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b" @@ -518,7 +518,7 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "de0752318171da717af4ce24d0a2e8626afaeb11" + revision = "aabede6cba87e37f413b3e60ebfc214f8eeca1b0" [[projects]] digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" @@ -538,14 +538,14 @@ [[projects]] branch = "master" - digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54" + digest = "1:ead82e3e398388679f3ad77633a087ac31a47a6be59ae20841e1d1b3a3fbbd22" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "4e1fef5609515ec7a2cee7b5de30ba6d9b438cbf" + revision = "1a700e749ce29638d0bbcb531cce1094ea096bd3" [[projects]] digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" @@ -576,7 +576,7 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "383e8b2c3b9e36c4076b235b32537292176bae20" + revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" diff --git a/Makefile b/Makefile index 2a7fd59b7..5603513eb 100644 --- a/Makefile +++ b/Makefile @@ -218,4 +218,4 @@ localnet-stop: check_tools check_dev_tools get_tools get_dev_tools get_vendor_deps draw_deps test test_cli test_unit \ test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \ build-linux build-docker-gaiadnode localnet-start localnet-stop \ -format check-ledger test_sim_modules test_sim_gaia_fast test_sim_gaia_slow update_tools update_dev_tools +format check-ledger test_sim_gaia_nondeterminism test_sim_modules test_sim_gaia_fast test_sim_gaia_slow update_tools update_dev_tools From 800ac2844e5e2e0857458aae3b548776c0f1c273 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Mon, 20 Aug 2018 17:10:43 +0200 Subject: [PATCH 66/97] validator.Operator, sdk.Dec --- cmd/gaia/app/sim_test.go | 12 ++++++------ x/gov/simulation/msgs.go | 4 ++-- x/stake/keeper/validator_test.go | 12 ++++++------ x/stake/simulation/msgs.go | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 8a81a1a92..051508e1a 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -59,18 +59,18 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json numInitiallyBonded := int64(50) for i := 0; i < int(numInitiallyBonded); i++ { validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) - validator.Tokens = sdk.NewRat(100) - validator.DelegatorShares = sdk.NewRat(100) - delegation := stake.Delegation{accs[i], accs[i], sdk.NewRat(100), 0} + validator.Tokens = sdk.NewDec(100) + validator.DelegatorShares = sdk.NewDec(100) + delegation := stake.Delegation{accs[i], accs[i], sdk.NewDec(100), 0} validators = append(validators, validator) delegations = append(delegations, delegation) } - stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*250) + (numInitiallyBonded * 100)) + stakeGenesis.Pool.LooseTokens = sdk.NewDec(int64(100*250) + (numInitiallyBonded * 100)) stakeGenesis.Validators = validators stakeGenesis.Bonds = delegations // No inflation, for now - stakeGenesis.Params.InflationMax = sdk.NewRat(0) - stakeGenesis.Params.InflationMin = sdk.NewRat(0) + stakeGenesis.Params.InflationMax = sdk.NewDec(0) + stakeGenesis.Params.InflationMin = sdk.NewDec(0) genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 596a013d3..ed80ab4e6 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -39,7 +39,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd if result.IsOK() { // Update pool to keep invariants pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom))) sk.SetPool(ctx, pool) write() } @@ -66,7 +66,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { if result.IsOK() { // Update pool to keep invariants pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom))) sk.SetPool(ctx, pool) write() } diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index d92ed8317..54149707e 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -102,8 +102,8 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { keeper.SetParams(ctx, params) // create a random pool - pool.LooseTokens = sdk.NewRat(10000) - pool.BondedTokens = sdk.NewRat(1234) + pool.LooseTokens = sdk.NewDec(10000) + pool.BondedTokens = sdk.NewDec(1234) keeper.SetPool(ctx, pool) validators := make([]types.Validator, numVals) @@ -123,13 +123,13 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // remove enough tokens to kick out the validator below the current cliff // validator and next in line cliff validator - nextCliffVal, pool, _ = nextCliffVal.RemoveDelShares(pool, sdk.NewRat(21)) + nextCliffVal, pool, _ = nextCliffVal.RemoveDelShares(pool, sdk.NewDec(21)) keeper.SetPool(ctx, pool) nextCliffVal = keeper.UpdateValidator(ctx, nextCliffVal) // require the cliff validator has changed cliffVal := validators[numVals-maxVals-1] - require.Equal(t, cliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, cliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) // require the cliff validator power has changed cliffPower := keeper.GetCliffValidatorPower(ctx) @@ -142,7 +142,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // require all the validators have their respective statuses for valIdx, status := range expectedValStatus { - valAddr := validators[valIdx].Owner + valAddr := validators[valIdx].Operator val, _ := keeper.GetValidator(ctx, valAddr) require.Equal( @@ -213,7 +213,7 @@ func TestCliffValidatorChange(t *testing.T) { // assert new cliff validator due to power rank construction newCliffVal = validators[numVals-maxVals+2] - require.Equal(t, newCliffVal.Owner, sdk.AccAddress(keeper.GetCliffValidator(ctx))) + require.Equal(t, newCliffVal.Operator, sdk.AccAddress(keeper.GetCliffValidator(ctx))) // assert cliff validator power should have been updated cliffPower = keeper.GetCliffValidatorPower(ctx) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index c457885fb..17f980893 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -236,8 +236,8 @@ func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { return func(r *rand.Rand, privKeys []crypto.PrivKey) { ctx := mapp.NewContext(false, abci.Header{}) gen := stake.DefaultGenesisState() - gen.Params.InflationMax = sdk.NewRat(0) - gen.Params.InflationMin = sdk.NewRat(0) + gen.Params.InflationMax = sdk.NewDec(0) + gen.Params.InflationMin = sdk.NewDec(0) stake.InitGenesis(ctx, k, gen) params := k.GetParams(ctx) denom := params.BondDenom From 9dd8e2810475c1fc802d903a262165ac92c80e98 Mon Sep 17 00:00:00 2001 From: Alexander Bezobchuk <alexanderbez@users.noreply.github.com> Date: Mon, 20 Aug 2018 15:15:25 -0400 Subject: [PATCH 67/97] Remove cosmosSignBytesPassword --- docs/ics/ics-030-signed-messages.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docs/ics/ics-030-signed-messages.md b/docs/ics/ics-030-signed-messages.md index 1e5b7c41a..e73d9f580 100644 --- a/docs/ics/ics-030-signed-messages.md +++ b/docs/ics/ics-030-signed-messages.md @@ -175,20 +175,6 @@ Returns: ----- -### **cosmosSignBytesPassword** - -Params: - -* `data`: the Cosmos signed message canonical JSON structure -* `address`: the Bech32 Cosmos account address to sign data with -* `password`: password of the account to sign data with - -Returns: - -* `signature`: the Cosmos signature derived using signing algorithm `S` - ------ - ### Examples Using the `secp256k1` as the DSA, `S`: From f076794c5a6a5d03d648e4a92e6af06904777394 Mon Sep 17 00:00:00 2001 From: Jae Kwon <jae@tendermint.com> Date: Mon, 20 Aug 2018 21:55:23 -0700 Subject: [PATCH 68/97] Fix bug introduced during merge --- x/stake/keeper/validator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 1a205a928..c828cc38e 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -425,7 +425,8 @@ func (k Keeper) UpdateBondedValidators( } newValidatorBonded = true } - + } else { + // TODO: document why we must break here. break } From 517682f17ccf43d11848cd83f369d81ca0ea74f4 Mon Sep 17 00:00:00 2001 From: youjing <youjing@huya.com> Date: Tue, 21 Aug 2018 14:54:12 +0800 Subject: [PATCH 69/97] fix Iterator leak, ref to https://github.com/cosmos/cosmos-sdk/issues/2105 --- examples/democoin/x/assoc/validator_set.go | 1 + examples/democoin/x/oracle/handler.go | 1 + store/iavlstore_test.go | 3 +++ x/auth/mapper.go | 1 + x/gov/keeper_test.go | 2 ++ x/gov/tally.go | 2 +- 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/democoin/x/assoc/validator_set.go b/examples/democoin/x/assoc/validator_set.go index 03ce506ea..ad89aab19 100644 --- a/examples/democoin/x/assoc/validator_set.go +++ b/examples/democoin/x/assoc/validator_set.go @@ -93,6 +93,7 @@ func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.AccAddress, asso func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.AccAddress) (res []sdk.AccAddress) { res = make([]sdk.AccAddress, valset.maxAssoc) iter := sdk.KVStorePrefixIterator(valset.store, GetAssocPrefix(base)) + defer iter.Close() i := 0 for ; iter.Valid(); iter.Next() { key := iter.Key() diff --git a/examples/democoin/x/oracle/handler.go b/examples/democoin/x/oracle/handler.go index 3c78fc566..1aaefc7e1 100644 --- a/examples/democoin/x/oracle/handler.go +++ b/examples/democoin/x/oracle/handler.go @@ -28,6 +28,7 @@ func (keeper Keeper) update(ctx sdk.Context, val sdk.Validator, valset sdk.Valid prefix := GetSignPrefix(p, keeper.cdc) store := ctx.KVStore(keeper.key) iter := sdk.KVStorePrefixIterator(store, prefix) + defer iter.Close() for ; iter.Valid(); iter.Next() { if valset.Validator(ctx, iter.Value()) != nil { store.Delete(iter.Key()) diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index d081b4576..38d85c658 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -168,6 +168,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { require.EqualValues(t, value, expectedKey) i++ } + iter.Close() require.Equal(t, len(expected), i) iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) @@ -183,6 +184,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { require.EqualValues(t, value, []byte("test4")) i++ } + iter.Close() require.Equal(t, len(expected), i) iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) @@ -198,6 +200,7 @@ func TestIAVLSubspaceIterator(t *testing.T) { require.EqualValues(t, value, []byte("test4")) i++ } + iter.Close() require.Equal(t, len(expected), i) } diff --git a/x/auth/mapper.go b/x/auth/mapper.go index 244527af3..c8bf94a21 100644 --- a/x/auth/mapper.go +++ b/x/auth/mapper.go @@ -87,6 +87,7 @@ func (am AccountMapper) SetAccount(ctx sdk.Context, acc Account) { func (am AccountMapper) IterateAccounts(ctx sdk.Context, process func(Account) (stop bool)) { store := ctx.KVStore(am.key) iter := sdk.KVStorePrefixIterator(store, []byte("account:")) + defer iter.Close() for { if !iter.Valid() { return diff --git a/x/gov/keeper_test.go b/x/gov/keeper_test.go index 442caee90..a61292b93 100644 --- a/x/gov/keeper_test.go +++ b/x/gov/keeper_test.go @@ -130,6 +130,7 @@ func TestDeposits(t *testing.T) { require.Equal(t, fourSteak, deposit.Amount) depositsIterator.Next() require.False(t, depositsIterator.Valid()) + depositsIterator.Close() // Test Refund Deposits deposit, found = keeper.GetDeposit(ctx, proposalID, addrs[1]) @@ -196,6 +197,7 @@ func TestVotes(t *testing.T) { require.Equal(t, OptionNoWithVeto, vote.Option) votesIterator.Next() require.False(t, votesIterator.Valid()) + votesIterator.Close() } func TestProposalQueues(t *testing.T) { diff --git a/x/gov/tally.go b/x/gov/tally.go index d8d4c7870..cfb113ae3 100644 --- a/x/gov/tally.go +++ b/x/gov/tally.go @@ -36,6 +36,7 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall // iterate over all the votes votesIterator := keeper.GetVotes(ctx, proposal.GetProposalID()) + defer votesIterator.Close() for ; votesIterator.Valid(); votesIterator.Next() { vote := &Vote{} keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), vote) @@ -64,7 +65,6 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall keeper.deleteVote(ctx, vote.ProposalID, vote.Voter) } - votesIterator.Close() // Iterate over the validators again to tally their voting power and see who didn't vote nonVoting = []sdk.AccAddress{} From d8d17df2c5753c292f53df9ef2485a20ffa5a9b9 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Tue, 21 Aug 2018 14:22:41 +0200 Subject: [PATCH 70/97] Correctly set variables in Makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5603513eb..3e0c36da6 100644 --- a/Makefile +++ b/Makefile @@ -20,16 +20,16 @@ check-ledger: ifeq ($(LEDGER_ENABLED),true) ifeq ($(UNAME_S),OpenBSD) $(info "OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988)") - TMP_BUILD_TAGS := $(BUILD_TAGS) - BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS)) +TMP_BUILD_TAGS := $(BUILD_TAGS) +BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS)) else ifndef GCC $(error "gcc not installed for ledger support, please install or set LEDGER_ENABLED to false in the Makefile") endif endif else - TMP_BUILD_TAGS := $(BUILD_TAGS) - BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS)) +TMP_BUILD_TAGS := $(BUILD_TAGS) +BUILD_TAGS = $(filter-out ledger, $(TMP_BUILD_TAGS)) endif build: check-ledger From e04e52451bffd85f81e02686985c371946a37332 Mon Sep 17 00:00:00 2001 From: youjing <youjing@huya.com> Date: Tue, 21 Aug 2018 20:23:53 +0800 Subject: [PATCH 71/97] Modify PENDING.md for #2105 --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index dafd653fe..f36d61320 100644 --- a/PENDING.md +++ b/PENDING.md @@ -105,3 +105,4 @@ BUG FIXES * \#1787 Fixed bug where Tally fails due to revoked/unbonding validator * [basecoin] Fixes coin transaction failure and account query [discussion](https://forum.cosmos.network/t/unmarshalbinarybare-expected-to-read-prefix-bytes-75fbfab8-since-it-is-registered-concrete-but-got-0a141dfa/664/6) * [cli] \#1997 Handle panics gracefully when `gaiacli stake {delegation,unbond}` fail to unmarshal delegation. +* \#2105 Fix DB Iterator leak, which may leak a go routine. From e2691d98fc49a4fef974d6bd21df74e5e4a72cb0 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Tue, 21 Aug 2018 15:40:43 +0200 Subject: [PATCH 72/97] 0.24.1 - Fix validator pubkey bug --- CHANGELOG.md | 9 +++++++++ version/version.go | 4 ++-- x/slashing/keeper.go | 8 ++++++-- x/slashing/keeper_test.go | 4 ++-- x/slashing/tick.go | 6 +----- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6b91607a..18b9d5348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.24.1 + +*August 21st, 2018* + +BUG FIXES + +* Gaia + - [x/slashing] Evidence tracking now uses validator address instead of validator pubkey + ## 0.24.0 *August 13th, 2018* diff --git a/version/version.go b/version/version.go index a2bee9eb2..707868ae0 100644 --- a/version/version.go +++ b/version/version.go @@ -3,9 +3,9 @@ package version const Maj = "0" const Min = "24" -const Fix = "0" +const Fix = "1" -const Version = "0.24.0" +const Version = "0.24.1" // GitCommit set by build flags var GitCommit = "" diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 2f163e57a..373423b2d 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -36,11 +36,15 @@ func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, params pa } // handle a validator signing two blocks at the same height -func (k Keeper) handleDoubleSign(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, timestamp time.Time, power int64) { +func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractionHeight int64, timestamp time.Time, power int64) { logger := ctx.Logger().With("module", "x/slashing") time := ctx.BlockHeader().Time age := time.Sub(timestamp) - address := sdk.ValAddress(pubkey.Address()) + address := sdk.ValAddress(addr) + pubkey, err := k.getPubkey(ctx, addr) + if err != nil { + panic(fmt.Sprintf("Validator address %v not found", addr)) + } // Double sign too old maxEvidenceAge := k.MaxEvidenceAge(ctx) diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index d3d6b06ed..dc65933f2 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -37,7 +37,7 @@ func TestHandleDoubleSign(t *testing.T) { keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) // double sign less than max age - keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) // should be revoked require.True(t, sk.Validator(ctx, addr).GetRevoked()) @@ -48,7 +48,7 @@ func TestHandleDoubleSign(t *testing.T) { ctx = ctx.WithBlockHeader(abci.Header{Time: time.Unix(1, 0).Add(keeper.MaxEvidenceAge(ctx))}) // double sign past max age - keeper.handleDoubleSign(ctx, val, 0, time.Unix(0, 0), amtInt) + keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt) require.Equal(t, sdk.NewRatFromInt(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower()) } diff --git a/x/slashing/tick.go b/x/slashing/tick.go index 7478b511c..253daa412 100644 --- a/x/slashing/tick.go +++ b/x/slashing/tick.go @@ -29,13 +29,9 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, sk Keeper) (tags // Slash any validators (and since-unbonded stake within the unbonding period) // who contributed to valid infractions for _, evidence := range req.ByzantineValidators { - pk, err := tmtypes.PB2TM.PubKey(evidence.Validator.PubKey) - if err != nil { - panic(err) - } switch evidence.Type { case tmtypes.ABCIEvidenceTypeDuplicateVote: - sk.handleDoubleSign(ctx, pk, evidence.Height, evidence.Time, evidence.Validator.Power) + sk.handleDoubleSign(ctx, evidence.Validator.Address, evidence.Height, evidence.Time, evidence.Validator.Power) default: ctx.Logger().With("module", "x/slashing").Error(fmt.Sprintf("ignored unknown evidence type: %s", evidence.Type)) } From f0b3766a465d2c833d05836c22a9ca7032a767a1 Mon Sep 17 00:00:00 2001 From: Joon <torecursedivine@gmail.com> Date: Tue, 21 Aug 2018 22:49:06 +0900 Subject: [PATCH 73/97] Merge PR #2074: Reject duplicate storekey name --- store/rootmultistore.go | 3 +++ store/rootmultistore_test.go | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/store/rootmultistore.go b/store/rootmultistore.go index 8eb1c33dd..04f8e44e6 100644 --- a/store/rootmultistore.go +++ b/store/rootmultistore.go @@ -68,6 +68,9 @@ func (rs *rootMultiStore) MountStoreWithDB(key StoreKey, typ StoreType, db dbm.D if _, ok := rs.storesParams[key]; ok { panic(fmt.Sprintf("rootMultiStore duplicate store key %v", key)) } + if _, ok := rs.keysByName[key.Name()]; ok { + panic(fmt.Sprintf("rootMultiStore duplicate store key name %v", key)) + } rs.storesParams[key] = storeParams{ key: key, typ: typ, diff --git a/store/rootmultistore_test.go b/store/rootmultistore_test.go index 79760d869..d6a714c66 100644 --- a/store/rootmultistore_test.go +++ b/store/rootmultistore_test.go @@ -21,6 +21,21 @@ func TestStoreType(t *testing.T) { } +func TestStoreMount(t *testing.T) { + db := dbm.NewMemDB() + store := NewCommitMultiStore(db) + + key1 := sdk.NewKVStoreKey("store1") + key2 := sdk.NewKVStoreKey("store2") + dup1 := sdk.NewKVStoreKey("store1") + + require.NotPanics(t, func() { store.MountStoreWithDB(key1, sdk.StoreTypeIAVL, db) }) + require.NotPanics(t, func() { store.MountStoreWithDB(key2, sdk.StoreTypeIAVL, db) }) + + require.Panics(t, func() { store.MountStoreWithDB(key1, sdk.StoreTypeIAVL, db) }) + require.Panics(t, func() { store.MountStoreWithDB(dup1, sdk.StoreTypeIAVL, db) }) +} + func TestMultistoreCommitLoad(t *testing.T) { var db dbm.DB = dbm.NewMemDB() if useDebugDB { From 011e61a8def6131033a2b3d40fd1fde63d5c55e7 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 21 Aug 2018 16:00:43 +0200 Subject: [PATCH 74/97] Merge PR #2066: Rename LCD endpoints (Docs) --- docs/light/api.md | 1024 +++++++++++++++++++++++++-------------------- 1 file changed, 581 insertions(+), 443 deletions(-) diff --git a/docs/light/api.md b/docs/light/api.md index d4e66eaf1..4507c9eb8 100644 --- a/docs/light/api.md +++ b/docs/light/api.md @@ -1,39 +1,42 @@ -# Cosmos Hub (Gaia) LCD API +# Cosmos Hub (Gaia-Lite) LCD API -This document describes the API that is exposed by the specific LCD implementation of the Cosmos -Hub (Gaia). Those APIs are exposed by a REST server and can easily be accessed over HTTP/WS(websocket) +This document describes the API that is exposed by the specific Light Client Daemon (LCD) implementation of the Cosmos Hub (Gaia). Those APIs are exposed by a REST server and can easily be accessed over HTTP/WS (websocket) connections. -The complete API is comprised of the sub-APIs of different modules. The modules in the Cosmos Hub -(Gaia) API are: +The complete API is comprised of the sub-APIs of different modules. The modules in the Cosmos Hub (Gaia-Lite) API are: -* ICS0 (TendermintAPI) -* ICS1 (KeyAPI) -* ICS20 (TokenAPI) -* ICS21 (StakingAPI) - not yet implemented -* ICS22 (GovernanceAPI) - not yet implemented +- ICS0 ([TendermintAPI](api.md#ics0---tendermintapi)) +- ICS1 ([KeyAPI](api.md#ics1---keyapi)) +- ICS20 ([TokenAPI](api.md#ics20---tokenapi)) +- ICS21 ([StakingAPI](api.md#ics21---stakingapi)) +- ICS22 ([GovernanceAPI](api.md#ics22---governanceapi)) +- ICS23 ([SlashingAPI](api.md#ics23---slashingapi)) Error messages my change and should be only used for display purposes. Error messages should not be used for determining the error type. -## ICS0 - TendermintAPI - not yet implemented +## ICS0 - TendermintAPI -Exposes the same functionality as the Tendermint RPC from a full node. It aims to have a very -similar API. +Exposes the same functionality as the Tendermint RPC from a full node. It aims to have a very similar API. -### /broadcast_tx_sync - POST +### POST /txs -url: /broadcast_tx_sync +- **URL**: `/txs` +- Query Parameters: + - `?return={sync|async|block}`: + - `return=sync`: Waits for the transaction to pass `CheckTx` + - `return=async`: Returns the request immediately after it is received by the server + - `return=block`: waits for for the transaction to be committed in a block +- POST Body: -Functionality: Submit a signed transaction synchronously. This returns a response from CheckTx. +```json +{ + "transaction": "string", + "return": "string", +} +``` -Parameters: - -| Parameter | Type | Default | Required | Description | -| ----------- | ------ | ------- | -------- | --------------- | -| transaction | string | null | true | signed tx bytes | - -Returns on success: +- Returns on success: ```json { @@ -49,121 +52,23 @@ Returns on success: } ``` -Returns on failure: - -```json -{ - "rest api":"2.0", - "code":500, - "error":"Could not submit the transaction synchronously.", - "result":{} -} -``` - -### /broadcast_tx_async - POST - -url: /broadcast_tx_async - -Functionality: Submit a signed transaction asynchronously. This does not return a response from CheckTx. - -Parameters: - -| Parameter | Type | Default | Required | Description | -| ----------- | ------ | ------- | -------- | --------------- | -| transaction | string | null | true | signed tx bytes | - -Returns on success: - -```json -{ - "rest api":"2.0", - "code":200, - "error":"", - "result": { - "code":0, - "hash":"E39AAB7A537ABAA237831742DCE1117F187C3C52", - "data":"", - "log":"" - } -} -``` - -Returns on failure: - -```json -{ - "rest api":"2.0", - "code":500, - "error":"Could not submit the transaction asynchronously.", - "result":{} -} -``` - -### /broadcast_tx_commit - POST - -url: /broadcast_tx_commit - -Functionality: Submit a signed transaction and waits for it to be committed in a block. - -Parameters: - -| Parameter | Type | Default | Required | Description | -| ----------- | ------ | ------- | -------- | --------------- | -| transaction | string | null | true | signed tx bytes | - -Returns on success: - -```json -{ - "rest api":"2.0", - "code":200, - "error":"", - "result":{ - "height":26682, - "hash":"75CA0F856A4DA078FC4911580360E70CEFB2EBEE", - "deliver_tx":{ - "log":"", - "data":"", - "code":0 - }, - "check_tx":{ - "log":"", - "data":"", - "code":0 - } -} -``` - -Returns on failure: - -```json -{ - "rest api":"2.0", - "code":500, - "error":"Could not commit the transaction.", - "result":{} -} -``` - ## ICS1 - KeyAPI This API exposes all functionality needed for key creation, signing and management. -### /keys - GET +### GET /keys -url: /keys - -Functionality: Gets a list of all the keys. - -Returns on success: +- **URL**: `/keys` +- **Functionality**: Gets a list of all the keys. +- Returns on success: ```json { - "rest api":"2.0", + "rest api":"1.0", "code":200, "error":"", "result":{ - "keys":[ + "account":[ { "name":"monkey", "address":"cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", @@ -180,73 +85,25 @@ Returns on success: } ``` -Returns on failure: +### POST /keys + +- **URL**: `/keys` +- **Functionality**: Create a new key. +- POST Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not retrieve the keys.", - "result":{} + "name": "string", + "password": "string", + "seed": "string", } ``` -### /keys/recover - POST - -url: /keys/recover - -Functionality: Recover your key from seed and persist it encrypted with the password. - -Parameter: - -| Parameter | Type | Default | Required | Description | -| --------- | ------ | ------- | -------- | ---------------- | -| name | string | null | true | name of key | -| password | string | null | true | password of key | -| seed | string | null | true | seed of key | - Returns on success: ```json { - "rest api":"2.0", - "code":200, - "error":"", - "result":{ - "address":"BD607C37147656A507A5A521AA9446EB72B2C907" - } -} -``` - -Returns on failure: - -```json -{ - "rest api":"2.0", - "code":500, - "error":"Could not recover the key.", - "result":{} -} -``` - -### /keys/create - POST - -url: /keys/create - -Functionality: Create a new key. - -Parameter: - -| Parameter | Type | Default | Required | Description | -| --------- | ------ | ------- | -------- | ---------------- | -| name | string | null | true | name of key | -| password | string | null | true | password of key | - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"1.0", "code":200, "error":"", "result":{ @@ -255,28 +112,15 @@ Returns on success: } ``` -Returns on failure: +### GET /keys/{name} + +- **URL** : `/keys/{name}` +- **Functionality**: Get the information for the specified key. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create new key.", - "result":{} -} -``` - -### /keys/{name} - GET - -url: /keys/{name} - -Functionality: Get the information for the specified key. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"1.0", "code":200, "error":"", "result":{ @@ -287,31 +131,20 @@ Returns on success: } ``` -Returns on failure: +### PUT /keys/{name} + +- **URL** : `/keys/{name}` +- **Functionality**: Change the encryption password for the specified key. +- PUT Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not find information on the specified key.", - "result":{} + "old_password": "string", + "new_password": "string", } ``` -### /keys/{name} - PUT - -url: /keys/{name} - -Functionality: Change the encryption password for the specified key. - -Parameters: - -| Parameter | Type | Default | Required | Description | -| --------------- | ------ | ------- | -------- | --------------- | -| old_password | string | null | true | old password | -| new_password | string | null | true | new password | - -Returns on success: +- Returns on success: ```json { @@ -322,48 +155,77 @@ Returns on success: } ``` -Returns on failure: +### DELETE /keys/{name} + +- **URL**: `/keys/{name}` +- **Functionality**: Delete the specified key. +- DELETE Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not update the specified key.", - "result":{} + "password": "string", } ``` -### /keys/{name} - DELETE - -url: /keys/{name} - -Functionality: Delete the specified key. - -Parameters: - -| Parameter | Type | Default | Required | Description | -| --------- | ------ | ------- | -------- | ---------------- | -| password | string | null | true | password of key | - -Returns on success: +- Returns on success: ```json { - "rest api":"2.0", + "rest api":"1.0", "code":200, "error":"", "result":{} } ``` -Returns on failure: +### POST /keys/{name}/recover + +- **URL**: `/keys/{name}/recover` +- **Functionality**: Recover your key from seed and persist it encrypted with the password. +- POST Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not delete the specified key.", - "result":{} + "password": "string", + "seed": "string", +} +``` + +- Returns on success: + +```json +{ + "rest api":"1.0", + "code":200, + "error":"", + "result":{ + "address":"BD607C37147656A507A5A521AA9446EB72B2C907" + } +} +``` + +### GET /auth/accounts/{address} + +- **URL**: `/auth/accounts/{address}` +- **Functionality**: Query the information of an account . +- Returns on success: + +```json +{ + "rest api":"1.0", + "code":200, + "error":"", + "result":{ + "address": "82A57F8575BDFA22F5164C75361A21D2B0E11089", + "public_key": "PubKeyEd25519{A0EEEED3C9CE1A6988DEBFE347635834A1C0EBA0B4BB1125896A7072D22E650D}", + "coins": [ + {"atom": 300}, + {"photon": 15} + ], + "account_number": 1, + "sequence": 7 + } +} } ``` @@ -371,13 +233,11 @@ Returns on failure: The TokenAPI exposes all functionality needed to query account balances and send transactions. -### /bank/balance/{account} - GET +### GET /bank/balance/{account} -url: /bank/balance/{account} - -Functionality: Query the specified account. - -Returns on success: +- **URL**: `/bank/balance/{account}` +- **Functionality**: Query the specified account's balance. +- Returns on success: ```json { @@ -392,34 +252,30 @@ Returns on success: } ``` -Returns on error: +### POST /bank/transfers + +- **URL**: `/bank/transfers` +- **Functionality**: Create a transfer in the bank module. +- POST Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not find any balance for the specified account.", - "result":{} + "amount": [ + { + "denom": "string", + "amount": 64, + } + ], + "name": "string", + "password": "string", + "chain_id": "string", + "account_number": 64, + "sequence": 64, + "gas": 64, } ``` -### /bank/create_transfer - POST - -url: /bank/create_transfer - -Functionality: Create a transfer in the bank module. - -Parameters: - -| Parameter | Type | Default | Required | Description | -| ------------ | ------ | ------- | -------- | ------------------------- | -| sender | string | null | true | Address of sender | -| receiver | string | null | true | address of receiver | -| chain_id | string | null | true | chain id | -| amount | int | null | true | amount of the token | -| denomonation | string | null | true | denomonation of the token | - -Returns on success: +- Returns on success: ```json { @@ -432,32 +288,19 @@ Returns on success: } ``` -Returns on failure: - -```json -{ - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} -} -``` - ## ICS21 - StakingAPI The StakingAPI exposes all functionality needed for validation and delegation in Proof-of-Stake. -### /stake/delegators/{delegatorAddr} - GET +### GET /stake/delegators/{delegatorAddr} -url: /stake/delegators/{delegatorAddr} - -Functionality: Get all delegations (delegation, undelegation) from a delegator. - -Returns on success: +- **URL**: `/stake/delegators/{delegatorAddr}` +- **Functionality**: Get all delegations (delegation, undelegation) from a delegator. +- Returns on success: ```json { - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result": { @@ -468,84 +311,45 @@ Returns on success: } ``` -Returns on error: +### GET /stake/delegators/{delegatorAddr}/validators + +- **URL**: `/stake/delegators/{delegatorAddr}/validators` +- **Functionality**: Query all validators that a delegator is bonded to. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not find any balance for the specified account.", - "result":{} -} -``` - -### /stake/delegators/{delegatorAddr}/validators - GET - -url: /stake/delegators/{delegatorAddr}/validators - -Functionality: Query all validators that a delegator is bonded to. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{} } ``` -Returns on failure: +### GET /stake/delegators/{delegatorAddr}/validators/{validatorAddr} + +- **URL**: `/stake/delegators/{delegatorAddr}/validators/{validatorAddr}` +- **Functionality**: Query a validator that a delegator is bonded to +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"TODO", - "result":{} -} -``` - -### /stake/delegators/{delegatorAddr}/validators/{validatorAddr} - GET - -url: /stake/delegators/{delegatorAddr}/validators/{validatorAddr} - -Functionality: Query a validator that a delegator is bonded to - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{} } ``` -Returns on failure: +### GET /stake/delegators/{delegatorAddr}/txs + +- **URL**: `/stake/delegators/{delegatorAddr}/txs` +- **Functionality**: Get all staking txs (i.e msgs) from a delegator. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"TODO", - "result":{} -} -``` - -### /stake/delegators/{delegatorAddr}/txs - GET - -url: /stake/delegators/{delegatorAddr}/txs - -Functionality: Get all staking txs (i.e msgs) from a delegator. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -554,28 +358,68 @@ Returns on success: } ``` -Returns on failure: +### POST /stake/delegators/{delegatorAddr}/delegations + +- **URL**: `/stake/delegators/{delegatorAddr}/delegations` +- **Functionality**: Submit or edit a delegation. + <!--NOTE Should this be a PUT instead of a POST? the code indicates that this is an edit operation--> +- POST Body: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} + "name": "string", + "password": "string", + "chain_id": "string", + "account_number": 64, + "sequence": 64, + "gas": 64, + "delegations": [ + { + "delegator_addr": "string", + "validator_addr": "string", + "delegation": { + "denom": "string", + "amount": 1234 + } + } + ], + "begin_unbondings": [ + { + "delegator_addr": "string", + "validator_addr": "string", + "shares": "string", + } + ], + "complete_unbondings": [ + { + "delegator_addr": "string", + "validator_addr": "string", + } + ], + "begin_redelegates": [ + { + "delegator_addr": "string", + "validator_src_addr": "string", + "validator_dst_addr": "string", + "shares": "string", + } + ], + "complete_redelegates": [ + { + "delegator_addr": "string", + "validator_src_addr": "string", + "validator_dst_addr": "string", + } + ] } + ``` -### /stake/delegators/{delegatorAddr}/delegations - POST - -url: /stake/delegators/{delegatorAddr}/delegations - -Functionality: Submit a delegation. - -Returns on success: +- Returns on success: ```json { - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -584,28 +428,15 @@ Returns on success: } ``` -Returns on failure: +### GET /stake/delegators/{delegatorAddr}/delegations/{validatorAddr} + +- **URL**: `/stake/delegators/{delegatorAddr}/delegations/{validatorAddr}` +- **Functionality**: Query the current delegation status between a delegator and a validator. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} -} -``` - -### /stake/delegators/{delegatorAddr}/delegations/{validatorAddr} - GET - -url: /stake/delegators/{delegatorAddr}/delegations/{validatorAddr} - -Functionality: Query the current delegation status between a delegator and a validator. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -614,28 +445,15 @@ Returns on success: } ``` -Returns on failure: +### GET /stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr} + +- **URL**: `/stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}` +- **Functionality**: Query all unbonding delegations between a delegator and a validator. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} -} -``` - -### /stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr} - GET - -url: /stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr} - -Functionality: Query all unbonding delegations between a delegator and a validator. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -644,28 +462,15 @@ Returns on success: } ``` -Returns on failure: +### GET /stake/validators + +- **URL**: `/stake/validators` +- **Functionality**: Get all validator candidates. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} -} -``` - -### /stake/validators - GET - -url: /stake/validators - -Functionality: Get all validator candidates. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -674,28 +479,15 @@ Returns on success: } ``` -Returns on failure: +### GET /stake/validators/{validatorAddr} + +- **URL**: `/stake/validators/{validatorAddr}` +- **Functionality**: Query the information from a single validator. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} -} -``` - -### /stake/validators/{validatorAddr} - GET - -url: /stake/validators/{validatorAddr} - -Functionality: Query the information from a single validator. - -Returns on success: - -```json -{ - "rest api":"2.0", + "rest api":"2.1", "code":200, "error":"", "result":{ @@ -704,13 +496,359 @@ Returns on success: } ``` -Returns on failure: +### GET /stake/parameters + +- **URL**: `/stake/parameters` +- **Functionality**: Get the current value of staking parameters. +- Returns on success: ```json { - "rest api":"2.0", - "code":500, - "error":"Could not create the transaction.", - "result":{} + "rest api":"2.1", + "code":200, + "error":"", + "result":{ + "inflation_rate_change": 1300000000, + "inflation_max": 2000000000, + "inflation_min": 700000000, + "goal_bonded": 6700000000, + "unbonding_time": "72h0m0s", + "max_validators": 100, + "bond_denom": "atom" + } +} +``` + +### GET /stake/pool + +- **URL**: `/stake/pool` +- **Functionality**: Get the current value of the dynamic parameters of the current state (*i.e* `Pool`). +- Returns on success: + +```json +{ + "rest api":"2.1", + "code":200, + "error":"", + "result":{ + "loose_tokens": 0, + "bonded_tokens": 0, + "inflation_last_time": "1970-01-01 01:00:00 +0100 CET", + "inflation": 700000000, + "date_last_commission_reset": 0, + "prev_bonded_shares": 0, + } +} +``` + +## ICS22 - GovernanceAPI + +The GovernanceAPI exposes all functionality needed for casting votes on plain text, software upgrades and parameter change proposals. + +### GET /gov/proposals + +- **URL**: `/gov/proposals` +- **Functionality**: Query all submited proposals +- Response on Success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "proposals":[ + "TODO" + ] + } +} +``` + +### POST /gov/proposals + +- **URL**: `/gov/proposals` +- **Functionality**: Submit a proposal +- POST Body: + +```js +{ + "base_req": { + // Name of key to use + "name": "string", + // Password for that key + "password": "string", + "chain_id": "string", + "account_number": 64, + "sequence": 64, + "gas": 64 + }, + // Title of the proposal + "title": "string", + // Description of the proposal + "description": "string", + // PlainTextProposal supported now. SoftwareUpgradeProposal and other types may be supported soon + "proposal_type": "string", + // A cosmosaccaddr address + "proposer": "string", + "initial_deposit": [ + { + "denom": "string", + "amount": 64, + } + ] +} +``` + +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "TODO": "TODO", + } +} +``` + +### GET /gov/proposals/{proposal-id} + +- **URL**: `/gov/proposals/{proposal-id}` +- **Functionality**: Query a proposal +- Response on Success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "proposal_id": 1, + "title": "Example title", + "description": "a larger description with the details of the proposal", + "proposal_type": "Text", + "proposal_status": "DepositPeriod", + "tally_result": { + "yes": 0, + "abstain": 0, + "no": 0, + "no_with_veto": 0 + }, + "submit_block": 5238512, + "total_deposit": {"atom": 50}, + "voting_start_block": -1 + } +} +``` + +### POST /gov/proposals/{proposal-id}/deposits + +- **URL**: `/gov/proposals/{proposal-id}/deposits` +- **Functionality**: Submit or rise a deposit to a proposal in order to make it active +- POST Body: + +```json +{ + "base_req": { + "name": "string", + "password": "string", + "chain_id": "string", + "account_number": 0, + "sequence": 0, + "gas": 0 + }, + "depositer": "string", + "amount": 0, +} +``` + +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "TODO": "TODO", + } +} +``` + +### GET /gov/proposals/{proposal-id}/deposits/{address} + +- **URL**: `/gov/proposals/{proposal-id}/deposits/{address}` +- **Functionality**: Query a validator's deposit to submit a proposal +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "amount": {"atom": 150}, + "depositer": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "proposal-id": 16 + } +} +``` + +### GET /gov/proposals/{proposal-id}/tally + +- **URL**: `/gov/proposals/{proposal-id}/tally` +- **Functionality**: Get the tally of a given proposal. +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result": { + "yes": 0, + "abstain": 0, + "no": 0, + "no_with_veto": 0 + } +} +``` + + + +### GET /gov/proposals/{proposal-id}/votes + +- **URL**: `/gov/proposals/{proposal-id}/votes` +- **Functionality**: Query all votes from a specific proposal +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result": [ + { + "proposal-id": 1, + "voter": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "option": "no_with_veto" + }, + { + "proposal-id": 1, + "voter": "cosmosaccaddr1849m9wncrqp6v4tkss6a3j8uzvuv0cp7f75lrq", + "option": "yes" + }, + ] +} +``` + + + +### POST /gov/proposals/{proposal-id}/votes + +- **URL**: `/gov/proposals/{proposal-id}/votes` +- **Functionality**: Vote for a specific proposal +- POST Body: + +```js +{ + "base_req": { + "name": "string", + "password": "string", + "chain_id": "string", + "account_number": 0, + "sequence": 0, + "gas": 0 + }, + // A cosmosaccaddr address + "voter": "string", + // Value of the vote option `Yes`, `No` `Abstain`, `NoWithVeto` + "option": "string", +} +``` + +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "TODO": "TODO", + } +} +``` + +### GET /gov/proposals/{proposal-id}/votes/{address} + +- **URL** : `/gov/proposals/{proposal-id}/votes/{address}` +- **Functionality**: Get the current `Option` submited by an address +- Returns on success: + +```json +{ + "rest api":"2.2", + "code":200, + "error":"", + "result":{ + "proposal-id": 1, + "voter": "cosmosaccaddr1fedh326uxqlxs8ph9ej7cf854gz7fd5zlym5pd", + "option": "no_with_veto" + } +} +``` + +## ICS23 - SlashingAPI + +The SlashingAPI exposes all functionalities needed to slash (*i.e* penalize) validators and delegators in Proof-of-Stake. The penalization is a fine of the staking coin and jail time, defined by governance parameters. During the jail period, the penalized validator is `Revoked`. + +### GET /slashing/validator/{validatorAddr}/signing-info + +- **URL**: `/slashing/validator/{validatorAddr}/signing-info` +- **Functionality**: Query the information from a single validator. +- Returns on success: + +```json +{ + "rest api":"2.3", + "code":200, + "error":"", + "result":{ + "transaction":"TODO" + } +} +``` + +### POST /slashing/validators/{validatorAddr}/unjail + +- **URL**: `/slashing/validators/{validatorAddr}/unjail` +- **Functionality**: Submit a message to unjail a validator after it has been penalized. +- POST Body: + +```js +{ + // Name of key to use + "name": "string", + // Password for that key + "password": "string", + "chain_id": "string", + "account_number": 64, + "sequence": 64, + "gas": 64, +} +``` + +- Returns on success: + +```json +{ + "rest api":"2.3", + "code":200, + "error":"", + "result":{ + "transaction":"TODO" + } } ``` From 419cf85433fb9b12883eefb7a9073d6e409daac2 Mon Sep 17 00:00:00 2001 From: Dev Ojha <ValarDragon@users.noreply.github.com> Date: Tue, 21 Aug 2018 07:13:34 -0700 Subject: [PATCH 75/97] Merge PR #2046: auth: Make gas cost take into account cryptosystem * auth: Make gas cost take into account cryptosystem This will make including the multisig easier. The ratio for ed25519 vs secp256k1 are based on the ratio of their verification times, using the benchmarks in tendermint/crypto. --- PENDING.md | 4 ++-- x/auth/ante.go | 25 ++++++++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/PENDING.md b/PENDING.md index f120b8ab8..c455419c9 100644 --- a/PENDING.md +++ b/PENDING.md @@ -20,7 +20,6 @@ BREAKING CHANGES * Tendermint - FEATURES * Gaia REST API (`gaiacli advanced rest-server`) @@ -42,7 +41,8 @@ IMPROVEMENTS * Gaia CLI (`gaiacli`) * Gaia - * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. + * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. + * [x/auth] Signature verification's gas cost now accounts for pubkey type. [#2046](https://github.com/tendermint/tendermint/pull/2046) * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. diff --git a/x/auth/ante.go b/x/auth/ante.go index 60aea8fc7..078f376e2 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -5,13 +5,17 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) const ( - deductFeesCost sdk.Gas = 10 - memoCostPerByte sdk.Gas = 1 - verifyCost = 100 - maxMemoCharacters = 100 + deductFeesCost sdk.Gas = 10 + memoCostPerByte sdk.Gas = 1 + ed25519VerifyCost = 59 + secp256k1VerifyCost = 100 + maxMemoCharacters = 100 ) // NewAnteHandler returns an AnteHandler that checks @@ -187,7 +191,7 @@ func processSig( } // Check sig. - ctx.GasMeter().ConsumeGas(verifyCost, "ante verify") + consumeSignatureVerificationGas(ctx.GasMeter(), pubKey) if !pubKey.VerifyBytes(signBytes, sig.Signature) { return nil, sdk.ErrUnauthorized("signature verification failed").Result() } @@ -195,6 +199,17 @@ func processSig( return } +func consumeSignatureVerificationGas(meter sdk.GasMeter, pubkey crypto.PubKey) { + switch pubkey.(type) { + case ed25519.PubKeyEd25519: + meter.ConsumeGas(ed25519VerifyCost, "ante verify: ed25519") + case secp256k1.PubKeySecp256k1: + meter.ConsumeGas(secp256k1VerifyCost, "ante verify: secp256k1") + default: + panic("Unrecognized signature type") + } +} + // Deduct the fee from the account. // We could use the CoinKeeper (in addition to the AccountMapper, // because the CoinKeeper doesn't give us accounts), but it seems easier to do this. From 68f5ee786c0c5e8d8b715b3619317305d2ad8a66 Mon Sep 17 00:00:00 2001 From: Jack Zampolin <jack.zampolin@gmail.com> Date: Tue, 21 Aug 2018 07:28:52 -0700 Subject: [PATCH 76/97] Merge PR #1987: Fix broken link in validator setup guide --- docs/validators/validator-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 38b453989..88a542dc0 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -4,7 +4,7 @@ The current testnet is `gaia-8000`. ::: -Before setting up your validator node, make sure you've already gone through the [Full Node Setup](/getting-started/full-node.md) guide. +Before setting up your validator node, make sure you've already gone through the [Full Node Setup](/docs/getting-started/full-node.md) guide. ## Running a Validator Node From cfb5acca6eff494364bdd6190c5e8a1ddbd9cb07 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 21 Aug 2018 17:32:54 +0200 Subject: [PATCH 77/97] Merge PR #2099: Query staking Pool and Params --- PENDING.md | 3 +- client/lcd/lcd_test.go | 36 +++++++++++++ cmd/gaia/cli_test/cli_test.go | 39 ++++++++++++++ cmd/gaia/cmd/gaiacli/main.go | 2 + docs/sdk/clients.md | 35 ++++++++++++ examples/basecoin/cmd/basecli/main.go | 10 ++++ x/stake/client/cli/query.go | 78 +++++++++++++++++++++++++++ x/stake/client/rest/query.go | 72 +++++++++++++++++++++++++ x/stake/types/params.go | 35 ++++++++++++ x/stake/types/pool.go | 37 ++++++++++++- 10 files changed, 345 insertions(+), 2 deletions(-) diff --git a/PENDING.md b/PENDING.md index c455419c9..7f297c0f3 100644 --- a/PENDING.md +++ b/PENDING.md @@ -23,8 +23,10 @@ BREAKING CHANGES FEATURES * Gaia REST API (`gaiacli advanced rest-server`) + * [lcd] Endpoints to query staking pool and params * Gaia CLI (`gaiacli`) + * [cli] Cmds to query staking pool and params * Gaia @@ -63,4 +65,3 @@ BUG FIXES * \#1988 Make us compile on OpenBSD (disable ledger) [#1988] (https://github.com/cosmos/cosmos-sdk/issues/1988) * Tendermint - diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 09c0eddd1..fbbf6a6cf 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -353,6 +353,42 @@ func TestTxs(t *testing.T) { require.Equal(t, resultTx.Height, indexedTxs[0].Height) } +func TestPoolParamsQuery(t *testing.T) { + _, password := "test", "1234567890" + addr, _ := CreateAddr(t, "test", password, GetKeyBase(t)) + cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) + defer cleanup() + + defaultParams := stake.DefaultParams() + + res, body := Request(t, port, "GET", "/stake/parameters", nil) + require.Equal(t, http.StatusOK, res.StatusCode, body) + + var params stake.Params + err := cdc.UnmarshalJSON([]byte(body), ¶ms) + require.Nil(t, err) + require.True(t, defaultParams.Equal(params)) + + res, body = Request(t, port, "GET", "/stake/pool", nil) + require.Equal(t, http.StatusOK, res.StatusCode, body) + require.NotNil(t, body) + + initialPool := stake.InitialPool() + initialPool.LooseTokens = initialPool.LooseTokens.Add(sdk.NewDec(100)) + initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewDec(100)) // Delegate tx on GaiaAppGenState + initialPool.LooseTokens = initialPool.LooseTokens.Add(sdk.NewDec(int64(50))) // freeFermionsAcc = 50 on GaiaAppGenState + + var pool stake.Pool + err = cdc.UnmarshalJSON([]byte(body), &pool) + require.Nil(t, err) + require.Equal(t, initialPool.DateLastCommissionReset, pool.DateLastCommissionReset) + require.Equal(t, initialPool.PrevBondedShares, pool.PrevBondedShares) + require.Equal(t, initialPool.BondedTokens, pool.BondedTokens) + require.Equal(t, initialPool.NextInflation(params), pool.Inflation) + initialPool = initialPool.ProcessProvisions(params) // provisions are added to the pool every hour + require.Equal(t, initialPool.LooseTokens, pool.LooseTokens) +} + func TestValidatorsQuery(t *testing.T) { cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{}) defer cleanup() diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 4f041d848..47a1949dd 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -117,6 +117,11 @@ func TestGaiaCLICreateValidator(t *testing.T) { fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %s %v", fooAddr, flags)) require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64()) + defaultParams := stake.DefaultParams() + initialPool := stake.InitialPool() + initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewDec(100)) // Delegate tx on GaiaAppGenState + initialPool = initialPool.ProcessProvisions(defaultParams) // provisions are added to the pool every hour + // create validator cvStr := fmt.Sprintf("gaiacli stake create-validator %v", flags) cvStr += fmt.Sprintf(" --from=%s", "bar") @@ -124,6 +129,8 @@ func TestGaiaCLICreateValidator(t *testing.T) { cvStr += fmt.Sprintf(" --amount=%v", "2steak") cvStr += fmt.Sprintf(" --moniker=%v", "bar-vally") + initialPool.BondedTokens = initialPool.BondedTokens.Add(sdk.NewDec(1)) + executeWrite(t, cvStr, app.DefaultKeyPass) tests.WaitForNextNBlocksTM(2, port) @@ -150,6 +157,14 @@ func TestGaiaCLICreateValidator(t *testing.T) { */ validator = executeGetValidator(t, fmt.Sprintf("gaiacli stake validator %s --output=json %v", barAddr, flags)) require.Equal(t, "1.0000000000", validator.Tokens.String()) + + params := executeGetParams(t, fmt.Sprintf("gaiacli stake parameters --output=json %v", flags)) + require.True(t, defaultParams.Equal(params)) + + pool := executeGetPool(t, fmt.Sprintf("gaiacli stake pool --output=json %v", flags)) + require.Equal(t, initialPool.DateLastCommissionReset, pool.DateLastCommissionReset) + require.Equal(t, initialPool.PrevBondedShares, pool.PrevBondedShares) + require.Equal(t, initialPool.BondedTokens, pool.BondedTokens) } func TestGaiaCLISubmitProposal(t *testing.T) { @@ -328,6 +343,9 @@ func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount { return acc } +//___________________________________________________________________________________ +// stake + func executeGetValidator(t *testing.T, cmdStr string) stake.Validator { out := tests.ExecuteT(t, cmdStr, "") var validator stake.Validator @@ -337,6 +355,27 @@ func executeGetValidator(t *testing.T, cmdStr string) stake.Validator { return validator } +func executeGetPool(t *testing.T, cmdStr string) stake.Pool { + out := tests.ExecuteT(t, cmdStr, "") + var pool stake.Pool + cdc := app.MakeCodec() + err := cdc.UnmarshalJSON([]byte(out), &pool) + require.NoError(t, err, "out %v\n, err %v", out, err) + return pool +} + +func executeGetParams(t *testing.T, cmdStr string) stake.Params { + out := tests.ExecuteT(t, cmdStr, "") + var params stake.Params + cdc := app.MakeCodec() + err := cdc.UnmarshalJSON([]byte(out), ¶ms) + require.NoError(t, err, "out %v\n, err %v", out, err) + return params +} + +//___________________________________________________________________________________ +// gov + func executeGetProposal(t *testing.T, cmdStr string) gov.Proposal { out := tests.ExecuteT(t, cmdStr, "") var proposal gov.Proposal diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 02a96b614..d447504af 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -88,6 +88,8 @@ func main() { stakecmd.GetCmdQueryValidators("stake", cdc), stakecmd.GetCmdQueryDelegation("stake", cdc), stakecmd.GetCmdQueryDelegations("stake", cdc), + stakecmd.GetCmdQueryParams("stake", cdc), + stakecmd.GetCmdQueryPool("stake", cdc), stakecmd.GetCmdQueryUnbondingDelegation("stake", cdc), stakecmd.GetCmdQueryUnbondingDelegations("stake", cdc), stakecmd.GetCmdQueryRedelegation("stake", cdc), diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 2432cbc0d..be42a46db 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -341,6 +341,41 @@ gaiacli gov query-vote \ --voter=<account_cosmosaccaddr> ``` +#### Query Parameters + +You can get the current parameters that define high level settings for staking: + +``` +gaiacli stake parameters +``` + +With the above command you will get the values for: + +- Maximum and minumum Inflation rate +- Maximum annual change in inflation rate, +- Goal of bonded tokens (%) +- Unbonding time +- Maximum numbers of validators +- Coin denomination for staking + +All this values can be updated though a `governance` process by submitting a parameter change `proposal`. + +#### Query Pool + +A staking `Pool` defines the dynamic parameters of the current state. You can query them with the following command: + +``` +gaiacli stake pool +``` + +With the `pool` command you will get the values for: + +- Loose and bonded tokens +- Token supply +- Current anual inflation and the block in which the last inflation was processed +- Last recorded bonded shares + + ## Gaia-Lite ::: tip Note diff --git a/examples/basecoin/cmd/basecli/main.go b/examples/basecoin/cmd/basecli/main.go index 82a283515..15bfd8035 100644 --- a/examples/basecoin/cmd/basecli/main.go +++ b/examples/basecoin/cmd/basecli/main.go @@ -14,6 +14,7 @@ import ( authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli" + slashingcmd "github.com/cosmos/cosmos-sdk/x/slashing/client/cli" stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli" "github.com/spf13/cobra" "github.com/tendermint/tendermint/libs/cli" @@ -51,6 +52,13 @@ func main() { stakecmd.GetCmdQueryValidators("stake", cdc), stakecmd.GetCmdQueryDelegation("stake", cdc), stakecmd.GetCmdQueryDelegations("stake", cdc), + stakecmd.GetCmdQueryPool("stake", cdc), + stakecmd.GetCmdQueryParams("stake", cdc), + stakecmd.GetCmdQueryUnbondingDelegation("stake", cdc), + stakecmd.GetCmdQueryUnbondingDelegations("stake", cdc), + stakecmd.GetCmdQueryRedelegation("stake", cdc), + stakecmd.GetCmdQueryRedelegations("stake", cdc), + slashingcmd.GetCmdQuerySigningInfo("slashing", cdc), authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)), )...) @@ -63,6 +71,8 @@ func main() { stakecmd.GetCmdEditValidator(cdc), stakecmd.GetCmdDelegate(cdc), stakecmd.GetCmdUnbond("stake", cdc), + stakecmd.GetCmdRedelegate("stake", cdc), + slashingcmd.GetCmdUnrevoke(cdc), )...) // add proxy, version and key info diff --git a/x/stake/client/cli/query.go b/x/stake/client/cli/query.go index bdf4bb198..4b8e99e7d 100644 --- a/x/stake/client/cli/query.go +++ b/x/stake/client/cli/query.go @@ -417,3 +417,81 @@ func GetCmdQueryRedelegations(storeName string, cdc *wire.Codec) *cobra.Command return cmd } + +// GetCmdQueryPool implements the pool query command. +func GetCmdQueryPool(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "pool", + Short: "Query the current staking pool values", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + key := stake.PoolKey + cliCtx := context.NewCLIContext().WithCodec(cdc) + + res, err := cliCtx.QueryStore(key, storeName) + if err != nil { + return err + } + + pool := types.MustUnmarshalPool(cdc, res) + + switch viper.Get(cli.OutputFlag) { + case "text": + human := pool.HumanReadableString() + + fmt.Println(human) + + case "json": + // parse out the pool + output, err := wire.MarshalJSONIndent(cdc, pool) + if err != nil { + return err + } + + fmt.Println(string(output)) + } + return nil + }, + } + + return cmd +} + +// GetCmdQueryPool implements the params query command. +func GetCmdQueryParams(storeName string, cdc *wire.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "parameters", + Short: "Query the current staking parameters information", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + key := stake.ParamKey + cliCtx := context.NewCLIContext().WithCodec(cdc) + + res, err := cliCtx.QueryStore(key, storeName) + if err != nil { + return err + } + + params := types.MustUnmarshalParams(cdc, res) + + switch viper.Get(cli.OutputFlag) { + case "text": + human := params.HumanReadableString() + + fmt.Println(human) + + case "json": + // parse out the params + output, err := wire.MarshalJSONIndent(cdc, params) + if err != nil { + return err + } + + fmt.Println(string(output)) + } + return nil + }, + } + + return cmd +} diff --git a/x/stake/client/rest/query.go b/x/stake/client/rest/query.go index 036a3b451..a040c7541 100644 --- a/x/stake/client/rest/query.go +++ b/x/stake/client/rest/query.go @@ -68,6 +68,18 @@ func registerQueryRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Cod validatorHandlerFn(cliCtx, cdc), ).Methods("GET") + // Get the current state of the staking pool + r.HandleFunc( + "/stake/pool", + poolHandlerFn(cliCtx, cdc), + ).Methods("GET") + + // Get the current staking parameter values + r.HandleFunc( + "/stake/parameters", + paramsHandlerFn(cliCtx, cdc), + ).Methods("GET") + } // already resolve the rational shares to not handle this in the client @@ -554,3 +566,63 @@ func validatorHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.Handler w.Write(output) } } + +// HTTP request handler to query the pool information +func poolHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + key := stake.PoolKey + + res, err := cliCtx.QueryStore(key, storeName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("couldn't query pool. Error: %s", err.Error()))) + return + } + + pool, err := types.UnmarshalPool(cdc, res) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + output, err := cdc.MarshalJSON(pool) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Write(output) + } +} + +// HTTP request handler to query the staking params values +func paramsHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + key := stake.ParamKey + + res, err := cliCtx.QueryStore(key, storeName) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(fmt.Sprintf("couldn't query parameters. Error: %s", err.Error()))) + return + } + + params, err := types.UnmarshalParams(cdc, res) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + output, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + w.Write(output) + } +} diff --git a/x/stake/types/params.go b/x/stake/types/params.go index f297f3105..bad4251cb 100644 --- a/x/stake/types/params.go +++ b/x/stake/types/params.go @@ -2,9 +2,11 @@ package types import ( "bytes" + "fmt" "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" ) // defaultUnbondingTime reflects three weeks in seconds as the default @@ -43,3 +45,36 @@ func DefaultParams() Params { BondDenom: "steak", } } + +// HumanReadableString returns a human readable string representation of the +// parameters. +func (p Params) HumanReadableString() string { + + resp := "Pool \n" + resp += fmt.Sprintf("Maximum Annual Inflation Rate Change: %s\n", p.InflationRateChange) + resp += fmt.Sprintf("Max Inflation Rate: %s\n", p.InflationMax) + resp += fmt.Sprintf("Min Inflation Tate: %s\n", p.InflationMin) + resp += fmt.Sprintf("Bonded Token Goal (%s): %s\n", "s", p.GoalBonded) + resp += fmt.Sprintf("Unbonding Time: %s\n", p.UnbondingTime) + resp += fmt.Sprintf("Max Validators: %d: \n", p.MaxValidators) + resp += fmt.Sprintf("Bonded Coin Denomination: %s\n", p.BondDenom) + return resp +} + +// unmarshal the current staking params value from store key or panic +func MustUnmarshalParams(cdc *wire.Codec, value []byte) Params { + params, err := UnmarshalParams(cdc, value) + if err != nil { + panic(err) + } + return params +} + +// unmarshal the current staking params value from store key +func UnmarshalParams(cdc *wire.Codec, value []byte) (params Params, err error) { + err = cdc.UnmarshalBinary(value, ¶ms) + if err != nil { + return + } + return +} diff --git a/x/stake/types/pool.go b/x/stake/types/pool.go index d59c1ed25..b01ed8e9a 100644 --- a/x/stake/types/pool.go +++ b/x/stake/types/pool.go @@ -6,13 +6,14 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" ) // Pool - dynamic parameters of the current state type Pool struct { LooseTokens sdk.Dec `json:"loose_tokens"` // tokens which are not bonded in a validator BondedTokens sdk.Dec `json:"bonded_tokens"` // reserve of bonded tokens - InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed // TODO make time + InflationLastTime time.Time `json:"inflation_last_time"` // block which the last inflation was processed Inflation sdk.Dec `json:"inflation"` // current annual inflation rate DateLastCommissionReset int64 `json:"date_last_commission_reset"` // unix timestamp for last commission accounting reset (daily) @@ -123,3 +124,37 @@ func (p Pool) NextInflation(params Params) (inflation sdk.Dec) { return inflation } + +// HumanReadableString returns a human readable string representation of a +// pool. +func (p Pool) HumanReadableString() string { + + resp := "Pool \n" + resp += fmt.Sprintf("Loose Tokens: %s\n", p.LooseTokens) + resp += fmt.Sprintf("Bonded Tokens: %s\n", p.BondedTokens) + resp += fmt.Sprintf("Token Supply: %s\n", p.TokenSupply()) + resp += fmt.Sprintf("Bonded Ratio: %v\n", p.BondedRatio()) + resp += fmt.Sprintf("Previous Inflation Block: %s\n", p.InflationLastTime) + resp += fmt.Sprintf("Inflation: %v\n", p.Inflation) + resp += fmt.Sprintf("Date of Last Commission Reset: %d\n", p.DateLastCommissionReset) + resp += fmt.Sprintf("Previous Bonded Shares: %v\n", p.PrevBondedShares) + return resp +} + +// unmarshal the current pool value from store key or panics +func MustUnmarshalPool(cdc *wire.Codec, value []byte) Pool { + pool, err := UnmarshalPool(cdc, value) + if err != nil { + panic(err) + } + return pool +} + +// unmarshal the current pool value from store key +func UnmarshalPool(cdc *wire.Codec, value []byte) (pool Pool, err error) { + err = cdc.UnmarshalBinary(value, &pool) + if err != nil { + return + } + return +} From da30353394b633450e7d3094fdc1355d65a1935f Mon Sep 17 00:00:00 2001 From: rigelrozanski <rigel.rozanski@gmail.com> Date: Tue, 21 Aug 2018 16:39:10 -0400 Subject: [PATCH 78/97] update PR template --- .github/PULL_REQUEST_TEMPLATE.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6a2526059..36b9f97f2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,14 +5,14 @@ v If a checkbox is n/a - please still include it but + a little note why ☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > --> - [ ] Linked to github-issue with discussion and accepted design OR link to spec that describes this work. -- [ ] Updated all relevant documentation (`docs/`) -- [ ] Updated all relevant code comments - [ ] Wrote tests -- [ ] Added entries in `PENDING.md` that include links to the relevant issue or PR that most accurately describes the change. -- [ ] Updated `cmd/gaia` and `examples/` -- [ ] Read PR `Files changed` in the github PR explorer -___________________________________ +- [ ] Updated relevant documentation (`docs/`) +- [ ] Added entries in `PENDING.md` with issue # +- [ ] rereviewed `Files changed` in the github PR explorer + +______ + For Admin Use: -- [ ] Added appropriate labels to PR (ex. wip, ready-for-review, docs) -- [ ] Reviewers Assigned -- [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr)) +- Added appropriate labels to PR (ex. wip, ready-for-review, docs) +- Reviewers Assigned +- Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr)) From 937bc8ade025ae9d24583f87be11219f9136daf7 Mon Sep 17 00:00:00 2001 From: Jack Zampolin <jack.zampolin@gmail.com> Date: Tue, 21 Aug 2018 14:01:17 -0700 Subject: [PATCH 79/97] Fix issue with branches and circle --- .circleci/config.yml | 76 ++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 116bdc866..90a8393c1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,14 +39,6 @@ jobs: paths: - bin - profiles - - save_cache: - key: v1-pkg-cache - paths: - - /go/pkg - - save_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} - paths: - - /go/src/github.com/cosmos/cosmos-sdk lint: <<: *defaults @@ -54,10 +46,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: Get metalinter command: | @@ -75,10 +69,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: Test cli command: | @@ -91,10 +87,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: Test individual module simulations command: | @@ -107,10 +105,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: Test individual module simulations command: | @@ -123,10 +123,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: Test full Gaia simulation command: | @@ -139,10 +141,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-pkg-cache - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: mkdir -p /tmp/logs - run: name: Run tests @@ -166,8 +170,12 @@ jobs: steps: - attach_workspace: at: /tmp/workspace - - restore_cache: - key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - checkout + - run: + name: dependencies + command: | + export PATH="$GOBIN:$PATH" + make get_vendor_deps - run: name: gather command: | From f7d86752340f7002c764ad206c04a2ccdb567b90 Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Thu, 16 Aug 2018 01:03:25 -0700 Subject: [PATCH 80/97] Support a proposal JSON file in submit-proposal Closes #1852. Closes #1776. --- PENDING.md | 1 + .../simple-governance/submit-proposal.md | 17 ++++ x/gov/client/cli/tx.go | 82 +++++++++++++++++-- x/gov/client/cli/tx_test.go | 70 ++++++++++++++++ 4 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 x/gov/client/cli/tx_test.go diff --git a/PENDING.md b/PENDING.md index 7f297c0f3..d1e5ff938 100644 --- a/PENDING.md +++ b/PENDING.md @@ -27,6 +27,7 @@ FEATURES * Gaia CLI (`gaiacli`) * [cli] Cmds to query staking pool and params + * [gov][cli] #2062 added `--proposal` flag to `submit-proposal` that allows a JSON file containing a proposal to be passed in * Gaia diff --git a/docs/sdk/sdk-by-examples/simple-governance/submit-proposal.md b/docs/sdk/sdk-by-examples/simple-governance/submit-proposal.md index bb9eb289f..57571c151 100644 --- a/docs/sdk/sdk-by-examples/simple-governance/submit-proposal.md +++ b/docs/sdk/sdk-by-examples/simple-governance/submit-proposal.md @@ -6,6 +6,23 @@ Uuse the CLI to create a new proposal: simplegovcli propose --title="Voting Period update" --description="Should we change the proposal voting period to 3 weeks?" --deposit=300Atoms ``` +Or, via a json file: + +```bash +simplegovcli propose --proposal="path/to/proposal.json" +``` + +Where proposal.json contains: + +```json +{ + "title": "Voting Period Update", + "description": "Should we change the proposal voting period to 3 weeks?", + "type": "Text", + "deposit": "300Atoms" +} +``` + Get the details of your newly created proposal: ```bash diff --git a/x/gov/client/cli/tx.go b/x/gov/client/cli/tx.go index d19de9f07..44ca104cf 100644 --- a/x/gov/client/cli/tx.go +++ b/x/gov/client/cli/tx.go @@ -15,6 +15,9 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" + "io/ioutil" + "encoding/json" + "strings" ) const ( @@ -28,18 +31,51 @@ const ( flagDepositer = "depositer" flagStatus = "status" flagLatestProposalIDs = "latest" + flagProposal = "proposal" ) +type proposal struct { + Title string + Description string + Type string + Deposit string +} + +var proposalFlags = []string{ + flagTitle, + flagDescription, + flagProposalType, + flagDeposit, +} + // GetCmdSubmitProposal implements submitting a proposal transaction command. func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "submit-proposal", Short: "Submit a proposal along with an initial deposit", + Long: strings.TrimSpace(` +Submit a proposal along with an initial deposit. Proposal title, description, type and deposit can be given directly or through a proposal JSON file. For example: + +$ gaiacli gov submit-proposal --proposal="path/to/proposal.json" + +where proposal.json contains: + +{ + "title": "Test Proposal", + "description": "My awesome proposal", + "type": "Text", + "deposit": "1000test" +} + +is equivalent to + +$ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --deposit="1000test" +`), RunE: func(cmd *cobra.Command, args []string) error { - title := viper.GetString(flagTitle) - description := viper.GetString(flagDescription) - strProposalType := viper.GetString(flagProposalType) - initialDeposit := viper.GetString(flagDeposit) + proposal, err := parseSubmitProposalFlags() + if err != nil { + return err + } txCtx := authctx.NewTxContextFromCLI().WithCodec(cdc) cliCtx := context.NewCLIContext(). @@ -52,17 +88,17 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { return err } - amount, err := sdk.ParseCoins(initialDeposit) + amount, err := sdk.ParseCoins(proposal.Deposit) if err != nil { return err } - proposalType, err := gov.ProposalTypeFromString(strProposalType) + proposalType, err := gov.ProposalTypeFromString(proposal.Type) if err != nil { return err } - msg := gov.NewMsgSubmitProposal(title, description, proposalType, fromAddr, amount) + msg := gov.NewMsgSubmitProposal(proposal.Title, proposal.Description, proposalType, fromAddr, amount) err = msg.ValidateBasic() if err != nil { @@ -80,10 +116,42 @@ func GetCmdSubmitProposal(cdc *wire.Codec) *cobra.Command { cmd.Flags().String(flagDescription, "", "description of proposal") cmd.Flags().String(flagProposalType, "", "proposalType of proposal") cmd.Flags().String(flagDeposit, "", "deposit of proposal") + cmd.Flags().String(flagProposal, "", "proposal file path (if this path is given, other proposal flags are ignored)") return cmd } +func parseSubmitProposalFlags() (*proposal, error) { + proposal := &proposal{} + proposalFile := viper.GetString(flagProposal) + + if proposalFile == "" { + proposal.Title = viper.GetString(flagTitle) + proposal.Description = viper.GetString(flagDescription) + proposal.Type = viper.GetString(flagProposalType) + proposal.Deposit = viper.GetString(flagDeposit) + return proposal, nil + } + + for _, flag := range proposalFlags { + if viper.GetString(flag) != "" { + return nil, fmt.Errorf("--%s flag provided alongside --proposal, which is a noop", flag) + } + } + + contents, err := ioutil.ReadFile(proposalFile) + if err != nil { + return nil, err + } + + err = json.Unmarshal(contents, proposal) + if err != nil { + return nil, err + } + + return proposal, nil +} + // GetCmdDeposit implements depositing tokens for an active proposal. func GetCmdDeposit(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ diff --git a/x/gov/client/cli/tx_test.go b/x/gov/client/cli/tx_test.go new file mode 100644 index 000000000..0ddf992d9 --- /dev/null +++ b/x/gov/client/cli/tx_test.go @@ -0,0 +1,70 @@ +package cli + +import ( + "testing" + "github.com/spf13/viper" + "io/ioutil" + "github.com/stretchr/testify/require" +) + +func TestParseSubmitProposalFlags(t *testing.T) { + okJSON, err := ioutil.TempFile("", "proposal") + require.Nil(t, err, "unexpected error") + okJSON.WriteString(` +{ + "title": "Test Proposal", + "description": "My awesome proposal", + "type": "Text", + "deposit": "1000test" +} +`) + + badJSON, err := ioutil.TempFile("", "proposal") + require.Nil(t, err, "unexpected error") + badJSON.WriteString("bad json") + + // nonexistent json + viper.Set(flagProposal, "fileDoesNotExist") + _, err = parseSubmitProposalFlags() + require.Error(t, err) + + // invalid json + viper.Set(flagProposal, badJSON.Name()) + _, err = parseSubmitProposalFlags() + require.Error(t, err) + + // ok json + viper.Set(flagProposal, okJSON.Name()) + proposal1, err := parseSubmitProposalFlags() + require.Nil(t, err, "unexpected error") + require.Equal(t, "Test Proposal", proposal1.Title) + require.Equal(t, "My awesome proposal", proposal1.Description) + require.Equal(t, "Text", proposal1.Type) + require.Equal(t, "1000test", proposal1.Deposit) + + // flags that can't be used with --proposal + for _, incompatibleFlag := range proposalFlags { + viper.Set(incompatibleFlag, "some value") + _, err := parseSubmitProposalFlags() + require.Error(t, err) + viper.Set(incompatibleFlag, "") + } + + // no --proposal, only flags + viper.Set(flagProposal, "") + viper.Set(flagTitle, proposal1.Title) + viper.Set(flagDescription, proposal1.Description) + viper.Set(flagProposalType, proposal1.Type) + viper.Set(flagDeposit, proposal1.Deposit) + proposal2, err := parseSubmitProposalFlags() + require.Nil(t, err, "unexpected error") + require.Equal(t, proposal1.Title, proposal2.Title) + require.Equal(t, proposal1.Description, proposal2.Description) + require.Equal(t, proposal1.Type, proposal2.Type) + require.Equal(t, proposal1.Deposit, proposal2.Deposit) + + err = okJSON.Close() + require.Nil(t, err, "unexpected error") + err = badJSON.Close() + require.Nil(t, err, "unexpected error") +} From 0c0d282a0c3ab5a08f98493776c36cf202bb7742 Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Fri, 10 Aug 2018 23:42:57 -0700 Subject: [PATCH 81/97] Add plaintext flags to show keys; default print response to true; helptext updates Closes #1970 Closes #1971 Closes #1967 Closes #1969 --- Gopkg.lock | 197 ++++++------------------------------------- PENDING.md | 2 + client/flags.go | 2 +- client/keys/show.go | 43 +++++++++- client/keys/utils.go | 18 +++- client/tx/search.go | 17 +++- server/tm_cmds.go | 2 +- 7 files changed, 99 insertions(+), 182 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 38830c49e..e94ad3ec0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,76 +2,57 @@ [[projects]] - digest = "1:09a7f74eb6bb3c0f14d8926610c87f569c5cff68e978d30e9a3540aeb626fdf0" name = "github.com/bartekn/go-bip39" packages = ["."] - pruneopts = "UT" revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" [[projects]] branch = "master" - digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" name = "github.com/beorn7/perks" packages = ["quantile"] - pruneopts = "UT" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] - digest = "1:1343a2963481a305ca4d051e84bc2abd16b601ee22ed324f8d605de1adb291b0" name = "github.com/bgentry/speakeasy" packages = ["."] - pruneopts = "UT" revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" version = "v0.1.0" [[projects]] branch = "master" - digest = "1:70f6b224a59b2fa453debffa85c77f71063d8754b90c8c4fbad5794e2c382b0f" name = "github.com/brejski/hid" packages = ["."] - pruneopts = "UT" revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] - pruneopts = "UT" revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] - digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" name = "github.com/btcsuite/btcutil" packages = ["bech32"] - pruneopts = "UT" revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] - digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] - pruneopts = "UT" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" [[projects]] - digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b" name = "github.com/ebuchman/fail-test" packages = ["."] - pruneopts = "UT" revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" [[projects]] - digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" name = "github.com/fsnotify/fsnotify" packages = ["."] - pruneopts = "UT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -80,30 +61,24 @@ "metrics", "metrics/discard", "metrics/internal/lv", - "metrics/prometheus", + "metrics/prometheus" ] - pruneopts = "UT" revision = "4dc7be5d2d12881735283bcab7352178e190fc71" version = "v0.6.0" [[projects]] - digest = "1:31a18dae27a29aa074515e43a443abfd2ba6deb6d69309d8d7ce789c45f34659" name = "github.com/go-logfmt/logfmt" packages = ["."] - pruneopts = "UT" revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" version = "v0.3.0" [[projects]] - digest = "1:c4a2528ccbcabf90f9f3c464a5fc9e302d592861bbfd0b7135a7de8a943d0406" name = "github.com/go-stack/stack" packages = ["."] - pruneopts = "UT" revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -111,272 +86,213 @@ "proto", "protoc-gen-gogo/descriptor", "sortkeys", - "types", + "types" ] - pruneopts = "UT" revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp", + "ptypes/timestamp" ] - pruneopts = "UT" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" [[projects]] branch = "master" - digest = "1:4a0c6bb4805508a6287675fac876be2ac1182539ca8a32468d8128882e9d5009" name = "github.com/golang/snappy" packages = ["."] - pruneopts = "UT" revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" [[projects]] - digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" name = "github.com/gorilla/context" packages = ["."] - pruneopts = "UT" revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" [[projects]] - digest = "1:e73f5b0152105f18bc131fba127d9949305c8693f8a762588a82a48f61756f5f" name = "github.com/gorilla/mux" packages = ["."] - pruneopts = "UT" revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" version = "v1.6.2" [[projects]] - digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e" name = "github.com/gorilla/websocket" packages = ["."] - pruneopts = "UT" revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", - "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", "json/parser", "json/scanner", - "json/token", + "json/token" ] - pruneopts = "UT" revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" [[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] - pruneopts = "UT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] branch = "master" - digest = "1:39b27d1381a30421f9813967a5866fba35dc1d4df43a6eefe3b7a5444cb07214" name = "github.com/jmhodges/levigo" packages = ["."] - pruneopts = "UT" revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" [[projects]] branch = "master" - digest = "1:a64e323dc06b73892e5bb5d040ced475c4645d456038333883f58934abbf6f72" name = "github.com/kr/logfmt" packages = ["."] - pruneopts = "UT" revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" [[projects]] - digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7" name = "github.com/magiconair/properties" packages = ["."] - pruneopts = "UT" revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" [[projects]] - digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb" name = "github.com/mattn/go-isatty" packages = ["."] - pruneopts = "UT" revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" version = "v0.0.3" [[projects]] - digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] - pruneopts = "UT" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" version = "v1.0.1" [[projects]] branch = "master" - digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" name = "github.com/mitchellh/mapstructure" packages = ["."] - pruneopts = "UT" revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] - digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" name = "github.com/pelletier/go-toml" packages = ["."] - pruneopts = "UT" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" version = "v1.2.0" [[projects]] - digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" name = "github.com/pkg/errors" packages = ["."] - pruneopts = "UT" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" name = "github.com/pmezard/go-difflib" packages = ["difflib"] - pruneopts = "UT" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", - "prometheus/promhttp", + "prometheus/promhttp" ] - pruneopts = "UT" revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632" [[projects]] branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] - pruneopts = "UT" revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model", + "model" ] - pruneopts = "UT" revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfs", - "xfs", + "xfs" ] - pruneopts = "UT" revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" [[projects]] - digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c" name = "github.com/rcrowley/go-metrics" packages = ["."] - pruneopts = "UT" revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", - "mem", + "mem" ] - pruneopts = "UT" revision = "787d034dfe70e44075ccc060d346146ef53270ad" version = "v1.1.1" [[projects]] - digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" name = "github.com/spf13/cast" packages = ["."] - pruneopts = "UT" revision = "8965335b8c7107321228e3e3702cab9832751bac" version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] - pruneopts = "UT" revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" version = "v0.0.1" [[projects]] branch = "master" - digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] - pruneopts = "UT" revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] - digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] - pruneopts = "UT" revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" version = "v1.0.2" [[projects]] - digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" name = "github.com/spf13/viper" packages = ["."] - pruneopts = "UT" revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", - "require", + "require" ] - pruneopts = "UT" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" version = "v1.2.1" [[projects]] branch = "master" - digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -390,41 +306,33 @@ "leveldb/opt", "leveldb/storage", "leveldb/table", - "leveldb/util", + "leveldb/util" ] - pruneopts = "UT" revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", "edwards25519", - "extra25519", + "extra25519" ] - pruneopts = "UT" revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" [[projects]] - digest = "1:e0a2a4be1e20c305badc2b0a7a9ab7fef6da500763bec23ab81df3b5f9eec9ee" name = "github.com/tendermint/go-amino" packages = ["."] - pruneopts = "UT" revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" version = "v0.12.0-rc0" [[projects]] - digest = "1:d4a15d404afbf591e8be16fcda7f5ac87948d5c7531f9d909fd84cc730ab16e2" name = "github.com/tendermint/iavl" packages = ["."] - pruneopts = "UT" revision = "35f66e53d9b01e83b30de68b931f54b2477a94c9" version = "v0.9.2" [[projects]] - digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -484,22 +392,24 @@ "state/txindex/kv", "state/txindex/null", "types", - "version", + "version" ] - pruneopts = "UT" revision = "013b9cef642f875634c614019ab13b17570778ad" version = "v0.23.0" [[projects]] - digest = "1:4dcb0dd65feecb068ce23a234d1a07c7868a1e39f52a6defcae0bb371d03abf6" + name = "github.com/tendermint/tmlibs" + packages = ["cli"] + revision = "49596e0a1f48866603813df843c9409fc19805c6" + version = "v0.9.0" + +[[projects]] name = "github.com/zondax/ledger-goclient" packages = ["."] - pruneopts = "UT" revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [[projects]] branch = "master" - digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -515,13 +425,11 @@ "pbkdf2", "poly1305", "ripemd160", - "salsa20/salsa", + "salsa20/salsa" ] - pruneopts = "UT" revision = "aabede6cba87e37f413b3e60ebfc214f8eeca1b0" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -531,24 +439,20 @@ "idna", "internal/timeseries", "netutil", - "trace", + "trace" ] - pruneopts = "UT" revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f" [[projects]] branch = "master" - digest = "1:ead82e3e398388679f3ad77633a087ac31a47a6be59ae20841e1d1b3a3fbbd22" name = "golang.org/x/sys" packages = [ "cpu", - "unix", + "unix" ] - pruneopts = "UT" revision = "1a700e749ce29638d0bbcb531cce1094ea096bd3" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -564,22 +468,18 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable", + "unicode/rangetable" ] - pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - pruneopts = "UT" revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", @@ -606,69 +506,20 @@ "stats", "status", "tap", - "transport", + "transport" ] - pruneopts = "UT" revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" version = "v1.13.0" [[projects]] - digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" name = "gopkg.in/yaml.v2" packages = ["."] - pruneopts = "UT" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - input-imports = [ - "github.com/bartekn/go-bip39", - "github.com/bgentry/speakeasy", - "github.com/btcsuite/btcd/btcec", - "github.com/golang/protobuf/proto", - "github.com/gorilla/mux", - "github.com/mattn/go-isatty", - "github.com/pkg/errors", - "github.com/spf13/cobra", - "github.com/spf13/pflag", - "github.com/spf13/viper", - "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/require", - "github.com/tendermint/go-amino", - "github.com/tendermint/iavl", - "github.com/tendermint/tendermint/abci/server", - "github.com/tendermint/tendermint/abci/types", - "github.com/tendermint/tendermint/cmd/tendermint/commands", - "github.com/tendermint/tendermint/config", - "github.com/tendermint/tendermint/crypto", - "github.com/tendermint/tendermint/crypto/armor", - "github.com/tendermint/tendermint/crypto/ed25519", - "github.com/tendermint/tendermint/crypto/encoding/amino", - "github.com/tendermint/tendermint/crypto/merkle", - "github.com/tendermint/tendermint/crypto/secp256k1", - "github.com/tendermint/tendermint/crypto/tmhash", - "github.com/tendermint/tendermint/crypto/xsalsa20symmetric", - "github.com/tendermint/tendermint/libs/bech32", - "github.com/tendermint/tendermint/libs/cli", - "github.com/tendermint/tendermint/libs/cli/flags", - "github.com/tendermint/tendermint/libs/common", - "github.com/tendermint/tendermint/libs/db", - "github.com/tendermint/tendermint/libs/log", - "github.com/tendermint/tendermint/node", - "github.com/tendermint/tendermint/p2p", - "github.com/tendermint/tendermint/privval", - "github.com/tendermint/tendermint/proxy", - "github.com/tendermint/tendermint/rpc/client", - "github.com/tendermint/tendermint/rpc/core/types", - "github.com/tendermint/tendermint/rpc/lib/client", - "github.com/tendermint/tendermint/rpc/lib/server", - "github.com/tendermint/tendermint/types", - "github.com/tendermint/tendermint/version", - "github.com/zondax/ledger-goclient", - "golang.org/x/crypto/blowfish", - "golang.org/x/crypto/ripemd160", - ] + inputs-digest = "46c912cbb9fa9b2ab3529af18718edada64e59822c8a2e432aec9affa3e24f45" solver-name = "gps-cdcl" solver-version = 1 diff --git a/PENDING.md b/PENDING.md index 7f297c0f3..8ef5fa1e8 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,6 +8,8 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * [x/stake] Validator.Owner renamed to Validator.Operator * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id + * [cli] \#1983 --print-response now defaults to true in commands that create and send a transaction + * [cli] \#1983 you can now pass --pubkey or --address to gaiacli keys show to return a plaintext representation of the key's address or public key for use with other commands * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) diff --git a/client/flags.go b/client/flags.go index 8616f9e78..b02078905 100644 --- a/client/flags.go +++ b/client/flags.go @@ -52,7 +52,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously") c.Flags().Bool(FlagJson, false, "return output in json format") - c.Flags().Bool(FlagPrintResponse, false, "return tx response (only works with async = false)") + c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)") } return cmds } diff --git a/client/keys/show.go b/client/keys/show.go index 873c45a4b..7dbbc3028 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -4,10 +4,20 @@ import ( "encoding/json" "net/http" - keys "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/gorilla/mux" "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/pkg/errors" + "github.com/tendermint/tmlibs/cli" +) + +const ( + // FlagAddress is the flag for the user's address on the command line. + FlagAddress = "address" + // FlagPublicKey represents the user's public key on the command line. + FlagPublicKey = "pubkey" ) var showKeysCmd = &cobra.Command{ @@ -18,13 +28,38 @@ var showKeysCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { name := args[0] info, err := getKey(name) - if err == nil { - printInfo(info) + if err != nil { + return err } - return err + + showAddress := viper.GetBool(FlagAddress) + showPublicKey := viper.GetBool(FlagPublicKey) + outputSet := cmd.Flag(cli.OutputFlag).Changed + if showAddress && showPublicKey { + return errors.New("cannot use both --address and --pubkey at once") + } + if outputSet && (showAddress || showPublicKey) { + return errors.New("cannot use --output with --address or --pubkey") + } + if showAddress { + printKeyAddress(info) + return nil + } + if showPublicKey { + printPubKey(info) + return nil + } + + printInfo(info) + return nil }, } +func init() { + showKeysCmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") + showKeysCmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") +} + func getKey(name string) (keys.Info, error) { kb, err := GetKeyBase() if err != nil { diff --git a/client/keys/utils.go b/client/keys/utils.go index 907f9eda8..aa1b4bed9 100644 --- a/client/keys/utils.go +++ b/client/keys/utils.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/viper" - keys "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/tendermint/tendermint/libs/cli" dbm "github.com/tendermint/tendermint/libs/db" @@ -173,3 +173,19 @@ func printInfos(infos []keys.Info) { func printKeyOutput(ko KeyOutput) { fmt.Printf("%s\t%s\t%s\t%s\n", ko.Name, ko.Type, ko.Address, ko.PubKey) } + +func printKeyAddress(info keys.Info) { + ko, err := Bech32KeyOutput(info) + if err != nil { + panic(err) + } + fmt.Println(ko.Address.String()) +} + +func printPubKey(info keys.Info) { + ko, err := Bech32KeyOutput(info) + if err != nil { + panic(err) + } + fmt.Println(ko.PubKey) +} diff --git a/client/tx/search.go b/client/tx/search.go index adad29d7d..06b3c0972 100644 --- a/client/tx/search.go +++ b/client/tx/search.go @@ -27,7 +27,20 @@ const ( func SearchTxCmd(cdc *wire.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "txs", - Short: "Search for all transactions that match the given tags", + Short: "Search for all transactions that match the given tags.", + Long: strings.TrimSpace(` +Search for transactions that match the given tags. By default, transactions must match ALL tags +passed to the --tags option. To match any transaction, use the --any option. + +For example: + +$ gaiacli tendermint txs --tag test1,test2 + +will match any transaction tagged with both test1,test2. To match a transaction tagged with either +test1 or test2, use: + +$ gaiacli tendermint txs --tag test1,test2 --any +`), RunE: func(cmd *cobra.Command, args []string) error { tags := viper.GetStringSlice(flagTags) @@ -52,7 +65,7 @@ func SearchTxCmd(cdc *wire.Codec) *cobra.Command { // TODO: change this to false once proofs built in cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses") - cmd.Flags().StringSlice(flagTags, nil, "Tags that must match (may provide multiple)") + cmd.Flags().StringSlice(flagTags, nil, "Comma-separated list of tags that must match") cmd.Flags().Bool(flagAny, false, "Return transactions that match ANY tag, rather than ALL") return cmd } diff --git a/server/tm_cmds.go b/server/tm_cmds.go index f852b4029..c2395e399 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -69,7 +69,7 @@ func ShowValidatorCmd(ctx *Context) *cobra.Command { func UnsafeResetAllCmd(ctx *Context) *cobra.Command { return &cobra.Command{ Use: "unsafe-reset-all", - Short: "Reset blockchain database, priv_validator.json file, and the logger", + Short: "Resets the blockchain database, removes address book files, and resets priv_validator.json to the genesis state", RunE: func(cmd *cobra.Command, args []string) error { cfg := ctx.Config tcmd.ResetAll(cfg.DBDir(), cfg.P2P.AddrBookFile(), cfg.PrivValidatorFile(), ctx.Logger) From 3413a2bff1d8aa2b6bcb26652deecce57da0808b Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Tue, 21 Aug 2018 17:53:16 -0700 Subject: [PATCH 82/97] Remove --select in block command (#2060) Closes #1968. --- PENDING.md | 1 + client/rpc/block.go | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/PENDING.md b/PENDING.md index 7f297c0f3..159d4fa96 100644 --- a/PENDING.md +++ b/PENDING.md @@ -41,6 +41,7 @@ IMPROVEMENTS * [x/stake] \#2000 Added tests for new staking endpoints * Gaia CLI (`gaiacli`) + * [cli] #2060 removed `--select` from `block` command * Gaia * [x/stake] [#2023](https://github.com/cosmos/cosmos-sdk/pull/2023) Terminate iteration loop in `UpdateBondedValidators` and `UpdateBondedValidatorsFull` when the first revoked validator is encountered and perform a sanity check. diff --git a/client/rpc/block.go b/client/rpc/block.go index fb4376bc1..d16f38342 100644 --- a/client/rpc/block.go +++ b/client/rpc/block.go @@ -12,10 +12,6 @@ import ( "github.com/spf13/cobra" ) -const ( - flagSelect = "select" -) - //BlockCommand returns the verified block data for a given heights func BlockCommand() *cobra.Command { cmd := &cobra.Command{ @@ -27,7 +23,6 @@ func BlockCommand() *cobra.Command { cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:26657", "Node to connect to") // TODO: change this to false when we can cmd.Flags().Bool(client.FlagTrustNode, true, "Don't verify proofs for responses") - cmd.Flags().StringSlice(flagSelect, []string{"header", "tx"}, "Fields to return (header|txs|results)") return cmd } @@ -38,7 +33,6 @@ func getBlock(cliCtx context.CLIContext, height *int64) ([]byte, error) { return nil, err } - // TODO: actually honor the --select flag! // header -> BlockchainInfo // header, tx -> Block // results -> BlockResults From 62d6fd2f982ec453482a213fca9c58c03963a08d Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Tue, 21 Aug 2018 20:22:18 -0700 Subject: [PATCH 83/97] Merge PR #2014: Remove advanced gaiacli command Closes #1965 --- PENDING.md | 1 + cmd/gaia/cmd/gaiacli/main.go | 10 +--------- docs/clients/lcd-rest-api.yaml | 2 +- docs/clients/rest.md | 2 +- docs/validators/validator-setup.md | 2 +- .../ansible/roles/add-lcd/templates/gaiacli.service.j2 | 2 +- 6 files changed, 6 insertions(+), 13 deletions(-) diff --git a/PENDING.md b/PENDING.md index 159d4fa96..cb80119a9 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,6 +8,7 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * [x/stake] Validator.Owner renamed to Validator.Operator * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id + * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * Gaia * Make the transient store key use a distinct store key. [#2013](https://github.com/cosmos/cosmos-sdk/pull/2013) diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index d447504af..25c670bdd 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -62,18 +62,10 @@ func main() { ibccmd.IBCRelayCmd(cdc), )...) - advancedCmd := &cobra.Command{ - Use: "advanced", - Short: "Advanced subcommands", - } - - advancedCmd.AddCommand( + rootCmd.AddCommand( tendermintCmd, ibcCmd, lcd.ServeCommand(cdc), - ) - rootCmd.AddCommand( - advancedCmd, client.LineBreak, ) diff --git a/docs/clients/lcd-rest-api.yaml b/docs/clients/lcd-rest-api.yaml index 3b8349f4b..5be69302d 100644 --- a/docs/clients/lcd-rest-api.yaml +++ b/docs/clients/lcd-rest-api.yaml @@ -2,7 +2,7 @@ swagger: '2.0' info: version: '1.1.0' title: Gaia-Lite (former LCD) to interface with Cosmos BaseServer via REST - description: Specification for Gaia-lite provided by `gaiacli advanced rest-server` + description: Specification for Gaia-lite provided by `gaiacli rest-server` tags: - name: keys diff --git a/docs/clients/rest.md b/docs/clients/rest.md index 190eeb1f3..b48ec7d8f 100644 --- a/docs/clients/rest.md +++ b/docs/clients/rest.md @@ -1,6 +1,6 @@ # REST -See `gaiacli advanced rest-server --help` for more. +See `gaiacli rest-server --help` for more. Also see the [work in progress API specification](https://github.com/cosmos/cosmos-sdk/pull/1314) diff --git a/docs/validators/validator-setup.md b/docs/validators/validator-setup.md index 88a542dc0..e56c3c691 100644 --- a/docs/validators/validator-setup.md +++ b/docs/validators/validator-setup.md @@ -89,7 +89,7 @@ gaiacli stake unrevoke \ Your validator is active if the following command returns anything: ```bash -gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show-validator)" +gaiacli tendermint validator-set | grep "$(gaiad tendermint show-validator)" ``` You should also be able to see your validator on the [Explorer](https://explorecosmos.network/validators). You are looking for the `bech32` encoded `address` in the `~/.gaiad/config/priv_validator.json` file. diff --git a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 index 4f189f8f5..0d562163c 100644 --- a/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 +++ b/networks/remote/ansible/roles/add-lcd/templates/gaiacli.service.j2 @@ -8,7 +8,7 @@ Restart=on-failure User=gaiad Group=gaiad PermissionsStartOnly=true -ExecStart=/usr/bin/gaiacli advanced rest-server --laddr {{GAIAD_ADDRESS}} +ExecStart=/usr/bin/gaiacli rest-server --laddr {{GAIAD_ADDRESS}} ExecReload=/bin/kill -HUP $MAINPID KillSignal=SIGTERM From 5ce9b9af5a7c00f0a6d4f320538a03ec380521c6 Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Tue, 21 Aug 2018 20:28:16 -0700 Subject: [PATCH 84/97] Merge PR #2015: Change gaiad testnet example output flag Closes #1960. --- Makefile | 2 +- networks/local/README.md | 2 +- server/testnet.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 3e0c36da6..b35e3f5c9 100644 --- a/Makefile +++ b/Makefile @@ -204,7 +204,7 @@ build-docker-gaiadnode: # Run a 4-node testnet locally localnet-start: localnet-stop - @if ! [ -f build/node0/gaiad/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/gaiad:Z tendermint/gaiadnode testnet --v 4 --o . --starting-ip-address 192.168.10.2 ; fi + @if ! [ -f build/node0/gaiad/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/gaiad:Z tendermint/gaiadnode testnet --v 4 -o . --starting-ip-address 192.168.10.2 ; fi docker-compose up -d # Stop testnet diff --git a/networks/local/README.md b/networks/local/README.md index 3a0f855be..ef5e27803 100644 --- a/networks/local/README.md +++ b/networks/local/README.md @@ -61,7 +61,7 @@ rm -rf ./build make build-linux # Create configuration -docker run -v `pwd`/build:/gaiad tendermint/gaiadnode testnet --o . --v 1 +docker run -v `pwd`/build:/gaiad tendermint/gaiadnode testnet -o . --v 1 #Run the node docker run -v `pwd`/build:/gaiad tendermint/gaiadnode diff --git a/server/testnet.go b/server/testnet.go index d7e4ec9ac..93f563005 100644 --- a/server/testnet.go +++ b/server/testnet.go @@ -20,7 +20,7 @@ import ( var ( nodeDirPrefix = "node-dir-prefix" nValidators = "v" - outputDir = "o" + outputDir = "output-dir" startingIPAddress = "starting-ip-address" ) @@ -49,7 +49,7 @@ Example: } cmd.Flags().Int(nValidators, 4, "Number of validators to initialize the testnet with") - cmd.Flags().String(outputDir, "./mytestnet", + cmd.Flags().StringP(outputDir, "o", "./mytestnet", "Directory to store initialization data for the testnet") cmd.Flags().String(nodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") From d8f01be2118e1007c5eb56073c19927dd57be896 Mon Sep 17 00:00:00 2001 From: Matthew Slipper <me@matthewslipper.com> Date: Tue, 21 Aug 2018 20:44:13 -0700 Subject: [PATCH 85/97] Merge PR #2061: Change proposalID to proposal-id in gov REST Close #1963. --- PENDING.md | 1 + x/gov/client/rest/rest.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index cb80119a9..c4b04238c 100644 --- a/PENDING.md +++ b/PENDING.md @@ -8,6 +8,7 @@ BREAKING CHANGES * Gaia CLI (`gaiacli`) * [x/stake] Validator.Owner renamed to Validator.Operator * [cli] unsafe_reset_all, show_validator, and show_node_id have been renamed to unsafe-reset-all, show-validator, and show-node-id + * [cli] \#2061 changed proposalID in governance REST endpoints to proposal-id * [cli] \#2014 `gaiacli advanced` no longer exists - to access `ibc`, `rest-server`, and `validator-set` commands use `gaiacli ibc`, `gaiacli rest-server`, and `gaiacli tendermint`, respectively * Gaia diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index a410c7791..22283a652 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -17,7 +17,7 @@ import ( // REST Variable names // nolint const ( - RestProposalID = "proposalID" + RestProposalID = "proposal-id" RestDepositer = "depositer" RestVoter = "voter" RestProposalStatus = "status" From 1d1a95656a185586d5aeba1787a102fffecbe6e3 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Tue, 31 Jul 2018 18:48:32 -0700 Subject: [PATCH 86/97] custom queriables --- baseapp/baseapp.go | 65 +++++++++++++++++++++++++++++++++--------- baseapp/queryrouter.go | 51 +++++++++++++++++++++++++++++++++ types/queryable.go | 7 +++++ x/gov/queryable.go | 56 ++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 baseapp/queryrouter.go create mode 100644 types/queryable.go create mode 100644 x/gov/queryable.go diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index cf63f1f4d..22f592790 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -41,13 +41,14 @@ const ( // BaseApp reflects the ABCI application implementation. type BaseApp struct { // initialized on creation - Logger log.Logger - name string // application name from abci.Info - db dbm.DB // common DB backend - cms sdk.CommitMultiStore // Main (uncached) state - router Router // handle any kind of message - codespacer *sdk.Codespacer // handle module codespacing - txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx + Logger log.Logger + name string // application name from abci.Info + db dbm.DB // common DB backend + cms sdk.CommitMultiStore // Main (uncached) state + router Router // handle any kind of message + queryrouter QueryRouter // router for redirecting query calls + codespacer *sdk.Codespacer // handle module codespacing + txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx anteHandler sdk.AnteHandler // ante handler for fee and auth @@ -84,13 +85,14 @@ var _ abci.Application = (*BaseApp)(nil) // Accepts variable number of option functions, which act on the BaseApp to set configuration choices func NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp)) *BaseApp { app := &BaseApp{ - Logger: logger, - name: name, - db: db, - cms: store.NewCommitMultiStore(db), - router: NewRouter(), - codespacer: sdk.NewCodespacer(), - txDecoder: txDecoder, + Logger: logger, + name: name, + db: db, + cms: store.NewCommitMultiStore(db), + router: NewRouter(), + queryrouter: NewQueryRouter(), + codespacer: sdk.NewCodespacer(), + txDecoder: txDecoder, } // Register the undefined & root codespaces, which should not be used by @@ -135,6 +137,31 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { app.cms.MountStoreWithDB(key, typ, nil) } +<<<<<<< HEAD +======= +// nolint - Set functions +func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) { + app.initChainer = initChainer +} +func (app *BaseApp) SetBeginBlocker(beginBlocker sdk.BeginBlocker) { + app.beginBlocker = beginBlocker +} +func (app *BaseApp) SetEndBlocker(endBlocker sdk.EndBlocker) { + app.endBlocker = endBlocker +} +func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { + app.anteHandler = ah +} +func (app *BaseApp) SetAddrPeerFilter(pf sdk.PeerFilter) { + app.addrPeerFilter = pf +} +func (app *BaseApp) SetPubKeyPeerFilter(pf sdk.PeerFilter) { + app.pubkeyPeerFilter = pf +} +func (app *BaseApp) Router() Router { return app.router } +func (app *BaseApp) QueryRouter() QueryRouter { return app.queryrouter } + +>>>>>>> custom queriables // load latest application version func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error { err := app.cms.LoadLatestVersion() @@ -291,6 +318,8 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { return handleQueryStore(app, path, req) case "p2p": return handleQueryP2P(app, path, req) + case "custom": + return handleQueryCustom(app, path, req) } msg := "unknown query path" @@ -362,6 +391,14 @@ func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abc return sdk.ErrUnknownRequest(msg).QueryResult() } +func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { + // "/custom" prefix for keeper queries + queryable := app.queryrouter.Route(path[1]) + ctx := app.checkState.ctx + res, err := queryable.Query(ctx, path[2:], req) + return +} + // BeginBlock implements the ABCI application interface. func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { if app.cms.TracingEnabled() { diff --git a/baseapp/queryrouter.go b/baseapp/queryrouter.go new file mode 100644 index 000000000..0a6b4dfb1 --- /dev/null +++ b/baseapp/queryrouter.go @@ -0,0 +1,51 @@ +package baseapp + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// QueryRouter provides queryables for each query path. +type QueryRouter interface { + AddRoute(r string, h sdk.CustomQueryable) (rtr QueryRouter) + Route(path string) (h sdk.CustomQueryable) +} + +// map a transaction type to a handler and an initgenesis function +type queryroute struct { + r string + h sdk.CustomQueryable +} + +type queryrouter struct { + routes []queryroute +} + +// nolint +// NewRouter - create new router +// TODO either make Function unexported or make return type (router) Exported +func NewQueryRouter() *queryrouter { + return &queryrouter{ + routes: make([]queryroute, 0), + } +} + +// AddRoute - TODO add description +func (rtr *queryrouter) AddRoute(r string, h sdk.CustomQueryable) QueryRouter { + if !isAlphaNumeric(r) { + panic("route expressions can only contain alphanumeric characters") + } + rtr.routes = append(rtr.routes, queryroute{r, h}) + + return rtr +} + +// Route - TODO add description +// TODO handle expressive matches. +func (rtr *queryrouter) Route(path string) (h sdk.CustomQueryable) { + for _, route := range rtr.routes { + if route.r == path { + return route.h + } + } + return nil +} diff --git a/types/queryable.go b/types/queryable.go new file mode 100644 index 000000000..9ad36b8d2 --- /dev/null +++ b/types/queryable.go @@ -0,0 +1,7 @@ +package types + +import abci "github.com/tendermint/tendermint/abci/types" + +type CustomQueryable interface { + Query(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error) +} diff --git a/x/gov/queryable.go b/x/gov/queryable.go new file mode 100644 index 000000000..059d0d1db --- /dev/null +++ b/x/gov/queryable.go @@ -0,0 +1,56 @@ +package gov + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +type Querier struct { + keeper Keeper +} + +func NewQuerier(keeper Keeper) { + return Querier{ + keeper: keeper, + } +} + +func (keeper Keeper) Query(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + switch path[0] { + case "tally": + return QueryTally(ctx, path[1:], req) + case "proposal": + return handleMsgSubmitProposal(ctx, keeper, msg) + case MsgVote: + return handleMsgVote(ctx, keeper, msg) + default: + errMsg := "Unrecognized gov msg type" + return sdk.ErrUnknownRequest(errMsg).Result() + } +} + +func QueryProposal(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + var proposalID int64 + err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) + if err != nil { + return []byte{}, sdk.ErrUnknownRequest() + } + proposal := keeper.GetProposal(ctx, proposalID) + if proposal == nil { + return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + } + return keeper.cdc.MustMarshalBinary(proposal), nil +} + +func QueryTally(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + var proposalID int64 + err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) + if err != nil { + return []byte{}, sdk.ErrUnknownRequest() + } + proposal := keeper.GetProposal(ctx, proposalID) + if proposal == nil { + return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + } + passes, _ := tally(ctx, keeper, proposal) +} From 804baa70f442c5d23c70bf0bdb934a4fb1659790 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Fri, 3 Aug 2018 12:55:00 -0700 Subject: [PATCH 87/97] added querier to gov module --- baseapp/baseapp.go | 14 ++- baseapp/queryrouter.go | 10 +-- types/queryable.go | 5 +- x/gov/keeper.go | 60 +++++++++++++ x/gov/queryable.go | 189 +++++++++++++++++++++++++++++++++-------- 5 files changed, 230 insertions(+), 48 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 22f592790..8f08d2abf 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -393,10 +393,18 @@ func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abc func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { // "/custom" prefix for keeper queries - queryable := app.queryrouter.Route(path[1]) + querier := app.queryrouter.Route(path[1]) ctx := app.checkState.ctx - res, err := queryable.Query(ctx, path[2:], req) - return + resBytes, err := querier(ctx, path[2:], req) + if err != nil { + return abci.ResponseQuery{ + Code: uint32(err.ABCICode()), + } + } + return abci.ResponseQuery{ + Code: uint32(sdk.ABCICodeOK), + Value: resBytes, + } } // BeginBlock implements the ABCI application interface. diff --git a/baseapp/queryrouter.go b/baseapp/queryrouter.go index 0a6b4dfb1..ade071f1f 100644 --- a/baseapp/queryrouter.go +++ b/baseapp/queryrouter.go @@ -6,14 +6,14 @@ import ( // QueryRouter provides queryables for each query path. type QueryRouter interface { - AddRoute(r string, h sdk.CustomQueryable) (rtr QueryRouter) - Route(path string) (h sdk.CustomQueryable) + AddRoute(r string, h sdk.Querier) (rtr QueryRouter) + Route(path string) (h sdk.Querier) } // map a transaction type to a handler and an initgenesis function type queryroute struct { r string - h sdk.CustomQueryable + h sdk.Querier } type queryrouter struct { @@ -30,7 +30,7 @@ func NewQueryRouter() *queryrouter { } // AddRoute - TODO add description -func (rtr *queryrouter) AddRoute(r string, h sdk.CustomQueryable) QueryRouter { +func (rtr *queryrouter) AddRoute(r string, h sdk.Querier) QueryRouter { if !isAlphaNumeric(r) { panic("route expressions can only contain alphanumeric characters") } @@ -41,7 +41,7 @@ func (rtr *queryrouter) AddRoute(r string, h sdk.CustomQueryable) QueryRouter { // Route - TODO add description // TODO handle expressive matches. -func (rtr *queryrouter) Route(path string) (h sdk.CustomQueryable) { +func (rtr *queryrouter) Route(path string) (h sdk.Querier) { for _, route := range rtr.routes { if route.r == path { return route.h diff --git a/types/queryable.go b/types/queryable.go index 9ad36b8d2..9223332bc 100644 --- a/types/queryable.go +++ b/types/queryable.go @@ -2,6 +2,5 @@ package types import abci "github.com/tendermint/tendermint/abci/types" -type CustomQueryable interface { - Query(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error) -} +// Type for querier functions on keepers to implement to handle custom queries +type Querier = func(ctx Context, path []string, req abci.RequestQuery) (res []byte, err Error) diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 8a23ad248..45af4b471 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -108,6 +108,52 @@ func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposal Proposal) { store.Delete(KeyProposal(proposal.GetProposalID())) } +// nolint: gocyclo +// Get Proposal from store by ProposalID +func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest int64) []Proposal { + + maxProposalID, err := keeper.peekCurrentProposalID(ctx) + if err != nil { + return nil + } + + matchingProposals := []Proposal{} + + if numLatest <= 0 { + numLatest = maxProposalID + } + + for proposalID := maxProposalID - numLatest; proposalID < maxProposalID; proposalID++ { + if voterAddr != nil && len(voterAddr) != 0 { + _, found := keeper.GetVote(ctx, proposalID, voterAddr) + if !found { + continue + } + } + + if depositerAddr != nil && len(depositerAddr) != 0 { + _, found := keeper.GetDeposit(ctx, proposalID, depositerAddr) + if !found { + continue + } + } + + proposal := keeper.GetProposal(ctx, proposalID) + if proposal == nil { + continue + } + + if validProposalStatus(status) { + if proposal.GetStatus() != status { + continue + } + } + + matchingProposals = append(matchingProposals, proposal) + } + return matchingProposals +} + func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk.Error { store := ctx.KVStore(keeper.storeKey) bz := store.Get(KeyNextProposalID) @@ -131,6 +177,7 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) { return } +// Gets the next available ProposalID and increments it func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) { store := ctx.KVStore(keeper.storeKey) bz := store.Get(KeyNextProposalID) @@ -143,6 +190,19 @@ func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sd return proposalID, nil } +// Peeks the next available ProposalID without incrementing it +func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) { + store := ctx.KVStore(keeper.storeKey) + bz := store.Get(KeyNextProposalID) + if bz == nil { + return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set") + } + keeper.cdc.MustUnmarshalBinary(bz, &proposalID) + bz = keeper.cdc.MustMarshalBinary(proposalID + 1) + store.Set(KeyNextProposalID, bz) + return proposalID, nil +} + func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) { proposal.SetVotingStartBlock(ctx.BlockHeight()) proposal.SetStatus(StatusVotingPeriod) diff --git a/x/gov/queryable.go b/x/gov/queryable.go index 059d0d1db..c0e66d0bf 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -5,52 +5,167 @@ import ( abci "github.com/tendermint/tendermint/abci/types" ) -type Querier struct { - keeper Keeper -} - -func NewQuerier(keeper Keeper) { - return Querier{ - keeper: keeper, +func NewQuerier(keeper Keeper) sdk.Querier { + return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { + switch path[0] { + case "proposal": + return queryProposal(ctx, path[1:], req, keeper) + case "deposit": + return queryDeposit(ctx, path[1:], req, keeper) + case "vote": + return queryVote(ctx, path[1:], req, keeper) + case "deposits": + return queryDeposits(ctx, path[1:], req, keeper) + case "votes": + return queryVotes(ctx, path[1:], req, keeper) + case "proposals": + return queryProposals(ctx, path[1:], req, keeper) + case "tally": + return queryTally(ctx, path[1:], req, keeper) + default: + return nil, sdk.ErrUnknownRequest("unknown gov query endpoint") + } } } -func (keeper Keeper) Query(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { - switch path[0] { - case "tally": - return QueryTally(ctx, path[1:], req) - case "proposal": - return handleMsgSubmitProposal(ctx, keeper, msg) - case MsgVote: - return handleMsgVote(ctx, keeper, msg) - default: - errMsg := "Unrecognized gov msg type" - return sdk.ErrUnknownRequest(errMsg).Result() - } +// Params for query 'custom/gov/proposal' +type QueryProposalParams struct { + ProposalID int64 } -func QueryProposal(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { - var proposalID int64 - err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) - if err != nil { - return []byte{}, sdk.ErrUnknownRequest() +func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryProposalParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") } - proposal := keeper.GetProposal(ctx, proposalID) + + proposal := keeper.GetProposal(ctx, params.ProposalID) if proposal == nil { - return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + return []byte{}, ErrUnknownProposal(DefaultCodespace, params.ProposalID) } return keeper.cdc.MustMarshalBinary(proposal), nil } -func QueryTally(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { - var proposalID int64 - err := keeper.cdc.UnmarshalBinary(req.Data, proposalID) - if err != nil { - return []byte{}, sdk.ErrUnknownRequest() - } - proposal := keeper.GetProposal(ctx, proposalID) - if proposal == nil { - return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) - } - passes, _ := tally(ctx, keeper, proposal) +// Params for query 'custom/gov/deposit' +type QueryDepositParams struct { + ProposalID int64 + Depositer sdk.AccAddress +} + +func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryDepositParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, params) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } + + deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositer) + return keeper.cdc.MustMarshalBinary(deposit), nil +} + +// Params for query 'custom/gov/vote' +type QueryVoteParams struct { + ProposalID int64 + Voter sdk.AccAddress +} + +func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryVoteParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } + + vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter) + return keeper.cdc.MustMarshalBinary(vote), nil +} + +// Params for query 'custom/gov/deposits' +type QueryDepositsParams struct { + ProposalID int64 +} + +func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryDepositParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } + + var deposits []Deposit + depositsIterator := keeper.GetDeposits(ctx, params.ProposalID) + for ; depositsIterator.Valid(); depositsIterator.Next() { + deposit := Deposit{} + keeper.cdc.MustUnmarshalBinary(depositsIterator.Value(), &deposit) + deposits = append(deposits, deposit) + } + + return keeper.cdc.MustMarshalBinary(deposits), nil +} + +// Params for query 'custom/gov/votes' +type QueryVotesParams struct { + ProposalID int64 +} + +func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryVotesParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } + + var votes []Vote + votesIterator := keeper.GetVotes(ctx, params.ProposalID) + for ; votesIterator.Valid(); votesIterator.Next() { + vote := Vote{} + keeper.cdc.MustUnmarshalBinary(votesIterator.Value(), &vote) + votes = append(votes, vote) + } + + return keeper.cdc.MustMarshalBinary(votes), nil +} + +// Params for query 'custom/gov/proposals' +type QueryProposalsParams struct { + Voter sdk.AccAddress + Depositer sdk.AccAddress + ProposalStatus ProposalStatus + NumLatestProposals int64 +} + +func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + var params QueryProposalsParams + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } + + proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.NumLatestProposals) + + bz := keeper.cdc.MustMarshalBinary(proposals) + return bz, nil +} + +// Params for query 'custom/gov/tally' +type QueryTallyParams struct { + ProposalID int64 +} + +func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { + // TODO: Dependant on #1914 + + // var proposalID int64 + // err2 := keeper.cdc.UnmarshalBinary(req.Data, proposalID) + // if err2 != nil { + // return []byte{}, sdk.ErrUnknownRequest() + // } + + // proposal := keeper.GetProposal(ctx, proposalID) + // if proposal == nil { + // return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + // } + // _, tallyResult, _ := tally(ctx, keeper, proposal) + return nil, nil } From cc1d1fbcf71b73db123cac0b62ab4f63aee98f52 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Fri, 3 Aug 2018 14:43:13 -0700 Subject: [PATCH 88/97] moved queryrouter to behind baseapp seal --- baseapp/baseapp.go | 25 ------------------------- baseapp/setters.go | 6 ++++++ 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 8f08d2abf..6f143b156 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -137,31 +137,6 @@ func (app *BaseApp) MountStore(key sdk.StoreKey, typ sdk.StoreType) { app.cms.MountStoreWithDB(key, typ, nil) } -<<<<<<< HEAD -======= -// nolint - Set functions -func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) { - app.initChainer = initChainer -} -func (app *BaseApp) SetBeginBlocker(beginBlocker sdk.BeginBlocker) { - app.beginBlocker = beginBlocker -} -func (app *BaseApp) SetEndBlocker(endBlocker sdk.EndBlocker) { - app.endBlocker = endBlocker -} -func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) { - app.anteHandler = ah -} -func (app *BaseApp) SetAddrPeerFilter(pf sdk.PeerFilter) { - app.addrPeerFilter = pf -} -func (app *BaseApp) SetPubKeyPeerFilter(pf sdk.PeerFilter) { - app.pubkeyPeerFilter = pf -} -func (app *BaseApp) Router() Router { return app.router } -func (app *BaseApp) QueryRouter() QueryRouter { return app.queryrouter } - ->>>>>>> custom queriables // load latest application version func (app *BaseApp) LoadLatestVersion(mainKey sdk.StoreKey) error { err := app.cms.LoadLatestVersion() diff --git a/baseapp/setters.go b/baseapp/setters.go index 86a647d32..ef88b7fe5 100644 --- a/baseapp/setters.go +++ b/baseapp/setters.go @@ -74,6 +74,12 @@ func (app *BaseApp) Router() Router { } return app.router } +func (app *BaseApp) QueryRouter() QueryRouter { + if app.sealed { + panic("QueryRouter() on sealed BaseApp") + } + return app.queryrouter +} func (app *BaseApp) Seal() { app.sealed = true } func (app *BaseApp) IsSealed() bool { return app.sealed } func (app *BaseApp) enforceSeal() { From 13111176584b6a72bd00e4e5509b133387ed587f Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Sun, 5 Aug 2018 01:56:48 -0400 Subject: [PATCH 89/97] added to gov rest --- client/context/query.go | 5 ++ cmd/gaia/app/app.go | 3 + types/account.go | 23 ++++++ x/gov/client/rest/rest.go | 167 +++++++++++++++++--------------------- x/gov/depositsvotes.go | 32 ++++++++ x/gov/queryable.go | 2 +- 6 files changed, 139 insertions(+), 93 deletions(-) diff --git a/client/context/query.go b/client/context/query.go index 081f723b5..68676f741 100644 --- a/client/context/query.go +++ b/client/context/query.go @@ -31,6 +31,11 @@ func (ctx CLIContext) Query(path string) (res []byte, err error) { return ctx.query(path, nil) } +// Query information about the connected node with a data payload +func (ctx CLIContext) QueryWithData(path string, data []byte) (res []byte, err error) { + return ctx.query(path, data) +} + // QueryStore performs a query from a Tendermint node with the provided key and // store name. func (ctx CLIContext) QueryStore(key cmn.HexBytes, storeName string) (res []byte, err error) { diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index a96efa6b1..f79ffb306 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -105,6 +105,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)). AddRoute("gov", gov.NewHandler(app.govKeeper)) + app.QueryRouter(). + AddRoute("gov", gov.NewQuerier(app.govKeeper)) + // initialize BaseApp app.SetInitChainer(app.initChainer) app.SetBeginBlocker(app.BeginBlocker) diff --git a/types/account.go b/types/account.go index 92e2988f2..258a095e8 100644 --- a/types/account.go +++ b/types/account.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "encoding/hex" "encoding/json" "errors" @@ -108,6 +109,17 @@ func (bz AccAddress) Format(s fmt.State, verb rune) { } } +// Returns boolean for whether two AccAddresses are Equal +func (bz AccAddress) Equals(bz2 AccAddress) bool { + return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) +} + +// Returns boolean for whether an AccAddress is empty +func (bz AccAddress) Empty() bool { + bz2 := AccAddress{} + return bz.Equals(bz2) +} + //__________________________________________________________ // AccAddress a wrapper around bytes meant to represent a validator address @@ -192,6 +204,17 @@ func (bz ValAddress) Format(s fmt.State, verb rune) { } } +// Returns boolean for whether two ValAddresses are Equal +func (bz ValAddress) Equals(bz2 ValAddress) bool { + return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) +} + +// Returns boolean for whether an AccAddress is empty +func (bz ValAddress) Empty() bool { + bz2 := ValAddress{} + return bz.Equals(bz2) +} + // Bech32ifyAccPub takes AccountPubKey and returns the bech32 encoded string func Bech32ifyAccPub(pub crypto.PubKey) (string, error) { return bech32.ConvertAndEncode(Bech32PrefixAccPub, pub.Bytes()) diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 22283a652..cf5481da8 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -21,6 +21,7 @@ const ( RestDepositer = "depositer" RestVoter = "voter" RestProposalStatus = "status" + RestNumLatest = "latest" storeName = "gov" ) @@ -190,9 +191,13 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - err := errors.Errorf("proposalID [%d] does not exist", proposalID) + params := gov.QueryProposalParams{ + ProposalID: proposalID, + } + + res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(params)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return @@ -255,19 +260,14 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName) - if err != nil || len(res) == 0 { - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - w.WriteHeader(http.StatusNotFound) - err := errors.Errorf("proposalID [%d] does not exist", proposalID) - w.Write([]byte(err.Error())) + params := gov.QueryDepositParams{ + ProposalID: proposalID, + Depositer: depositerAddr, + } - return - } - - w.WriteHeader(http.StatusNotFound) - err = errors.Errorf("depositer [%s] did not deposit on proposalID [%d]", bechDepositerAddr, proposalID) + res, err := cliCtx.QueryWithData("custom/gov/deposit", cdc.MustMarshalBinary(params)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return @@ -283,7 +283,19 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - + if deposit.Empty() { + res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) + if err != nil || len(res) == 0 { + w.WriteHeader(http.StatusNotFound) + err := errors.Errorf("proposalID [%d] does not exist", proposalID) + w.Write([]byte(err.Error())) + return + } + w.WriteHeader(http.StatusNotFound) + err = errors.Errorf("depositer [%s] did not deposit on proposalID [%d]", bechDepositerAddr, proposalID) + w.Write([]byte(err.Error())) + return + } w.Write(output) } } @@ -328,19 +340,14 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName) - if err != nil || len(res) == 0 { - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - w.WriteHeader(http.StatusNotFound) - err := errors.Errorf("proposalID [%d] does not exist", proposalID) - w.Write([]byte(err.Error())) + params := gov.QueryVoteParams{ + Voter: voterAddr, + ProposalID: proposalID, + } - return - } - - w.WriteHeader(http.StatusNotFound) - err = errors.Errorf("voter [%s] did not vote on proposalID [%d]", bechVoterAddr, proposalID) + res, err := cliCtx.QueryWithData("custom/gov/vote", cdc.MustMarshalBinary(params)) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return @@ -356,7 +363,19 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - + if vote.Empty() { + res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) + if err != nil || len(res) == 0 { + w.WriteHeader(http.StatusNotFound) + err := errors.Errorf("proposalID [%d] does not exist", proposalID) + w.Write([]byte(err.Error())) + return + } + w.WriteHeader(http.StatusNotFound) + err = errors.Errorf("voter [%s] did not deposit on proposalID [%d]", bechVoterAddr, proposalID) + w.Write([]byte(err.Error())) + return + } w.Write(output) } } @@ -387,38 +406,19 @@ func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - err := errors.Errorf("proposalID [%d] does not exist", proposalID) - w.Write([]byte(err.Error())) - - return + params := gov.QueryVotesParams{ + ProposalID: proposalID, } - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - if proposal.GetStatus() != gov.StatusVotingPeriod { - err := errors.Errorf("proposal is not in Voting Period", proposalID) - w.Write([]byte(err.Error())) - - return - } - - res2, err := cliCtx.QuerySubspace(gov.KeyVotesSubspace(proposalID), storeName) + res, err := cliCtx.QueryWithData("custom/gov/votes", cdc.MustMarshalBinary(params)) if err != nil { - err = errors.New("ProposalID doesn't exist") + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } var votes []gov.Vote - - for i := 0; i < len(res2); i++ { - var vote gov.Vote - cdc.MustUnmarshalBinary(res2[i].Value, &vote) - votes = append(votes, vote) - } + cdc.MustUnmarshalBinary(res, &votes) output, err := wire.MarshalJSONIndent(cdc, votes) if err != nil { @@ -439,11 +439,13 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { bechVoterAddr := r.URL.Query().Get(RestVoter) bechDepositerAddr := r.URL.Query().Get(RestDepositer) strProposalStatus := r.URL.Query().Get(RestProposalStatus) + strNumLatest := r.URL.Query().Get(RestNumLatest) var err error var voterAddr sdk.AccAddress var depositerAddr sdk.AccAddress var proposalStatus gov.ProposalStatus + var numLatest int64 if len(bechVoterAddr) != 0 { voterAddr, err = sdk.AccAddressFromBech32(bechVoterAddr) @@ -476,54 +478,35 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { return } } + if len(strNumLatest) != 0 { + numLatest, err = strconv.ParseInt(strNumLatest, 10, 64) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + err := errors.Errorf("'%s' is not a valid int64", strNumLatest) + w.Write([]byte(err.Error())) + return + } + } cliCtx := context.NewCLIContext().WithCodec(cdc) - res, err := cliCtx.QueryStore(gov.KeyNextProposalID, storeName) + params := gov.QueryProposalsParams{ + Depositer: depositerAddr, + Voter: voterAddr, + ProposalStatus: proposalStatus, + NumLatestProposals: numLatest, + } + + res, err := cliCtx.QueryWithData("custom/gov/proposals", cdc.MustMarshalBinary(params)) if err != nil { - err = errors.New("no proposals exist yet and proposalID has not been set") + w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } - var maxProposalID int64 - cdc.MustUnmarshalBinary(res, &maxProposalID) - - matchingProposals := []gov.Proposal{} - - for proposalID := int64(0); proposalID < maxProposalID; proposalID++ { - if voterAddr != nil { - res, err = cliCtx.QueryStore(gov.KeyVote(proposalID, voterAddr), storeName) - if err != nil || len(res) == 0 { - continue - } - } - - if depositerAddr != nil { - res, err = cliCtx.QueryStore(gov.KeyDeposit(proposalID, depositerAddr), storeName) - if err != nil || len(res) == 0 { - continue - } - } - - res, err = cliCtx.QueryStore(gov.KeyProposal(proposalID), storeName) - if err != nil || len(res) == 0 { - continue - } - - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - if len(strProposalStatus) != 0 { - if proposal.GetStatus() != proposalStatus { - continue - } - } - - matchingProposals = append(matchingProposals, proposal) - } - + var matchingProposals []gov.Proposal + cdc.MustUnmarshalBinary(res, &matchingProposals) output, err := wire.MarshalJSONIndent(cdc, matchingProposals) if err != nil { w.WriteHeader(http.StatusBadRequest) diff --git a/x/gov/depositsvotes.go b/x/gov/depositsvotes.go index 19ed97f69..5a8b6bf24 100644 --- a/x/gov/depositsvotes.go +++ b/x/gov/depositsvotes.go @@ -15,6 +15,22 @@ type Vote struct { Option VoteOption `json:"option"` // option from OptionSet chosen by the voter } +// Returns whether 2 votes are equal +func (voteA Vote) Equals(voteB Vote) bool { + if voteA.Voter.Equals(voteB.Voter) && + voteA.ProposalID == voteB.ProposalID && + voteA.Option == voteB.Option { + return true + } + return false +} + +// Returns whether a vote is empty +func (voteA Vote) Empty() bool { + voteB := Vote{} + return voteA.Equals(voteB) +} + // Deposit type Deposit struct { Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer @@ -22,6 +38,22 @@ type Deposit struct { Amount sdk.Coins `json:"amount"` // Deposit amount } +// Returns whether 2 deposits are equal +func (depositA Deposit) Equals(depositB Deposit) bool { + if depositA.Depositer.Equals(depositB.Depositer) && + depositA.ProposalID == depositB.ProposalID && + depositA.Amount.IsEqual(depositB.Amount) { + return true + } + return false +} + +// Returns whether a deposit is empty +func (depositA Deposit) Empty() bool { + depositB := Deposit{} + return depositA.Equals(depositB) +} + // Type that represents VoteOption as a byte type VoteOption byte diff --git a/x/gov/queryable.go b/x/gov/queryable.go index c0e66d0bf..13bdfd08d 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -55,7 +55,7 @@ type QueryDepositParams struct { func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryDepositParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, params) + err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) if err2 != nil { return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") } From 0eed9d1b60375dae6ff0d0d7104a5cb727988cac Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Mon, 6 Aug 2018 05:09:16 -0400 Subject: [PATCH 90/97] PENDING --- PENDING.md | 1 + docs/sdk/modules.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/PENDING.md b/PENDING.md index c4b04238c..53bdb91ca 100644 --- a/PENDING.md +++ b/PENDING.md @@ -33,6 +33,7 @@ FEATURES * Gaia * SDK + * [querier] added custom querier functionality, so ABCI query requests can be handled by keepers * Tendermint diff --git a/docs/sdk/modules.md b/docs/sdk/modules.md index b9249cf3e..7df8fb2bb 100644 --- a/docs/sdk/modules.md +++ b/docs/sdk/modules.md @@ -6,7 +6,7 @@ The Cosmos SDK has all the necessary pre-built modules to add functionality on top of a `BaseApp`, which is the template to build a blockchain dApp in Cosmos. In this context, a `module` is a fundamental unit in the Cosmos SDK. -Each module is an extension of the `BaseApp`'s functionalities that defines transactions, handles application state and manages the state transition logic. Each module also contains handlers for messages and transactions, as well as REST and CLI for secure user interactions. +Each module is an extension of the `BaseApp`'s functionalities that defines transactions, handles application state and manages the state transition logic. Each module also contains handlers for messages and transactions, queriers for handling query requests, as well as REST and CLI for secure user interactions. Some of the most important modules in the SDK are: From 0134c3b7f1d96278308e229ace4a956101a351b8 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Wed, 15 Aug 2018 17:59:15 -0700 Subject: [PATCH 91/97] Address Anton's comments --- baseapp/baseapp.go | 12 ++++++--- baseapp/setters.go | 2 +- x/gov/client/rest/rest.go | 57 ++++++++++++--------------------------- x/gov/client/rest/util.go | 14 ++++++++++ x/gov/depositsvotes.go | 14 ++-------- x/gov/keeper.go | 2 -- 6 files changed, 42 insertions(+), 59 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 6f143b156..aadea1561 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -46,7 +46,7 @@ type BaseApp struct { db dbm.DB // common DB backend cms sdk.CommitMultiStore // Main (uncached) state router Router // handle any kind of message - queryrouter QueryRouter // router for redirecting query calls + queryRouter QueryRouter // router for redirecting query calls codespacer *sdk.Codespacer // handle module codespacing txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx @@ -90,7 +90,7 @@ func NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecod db: db, cms: store.NewCommitMultiStore(db), router: NewRouter(), - queryrouter: NewQueryRouter(), + queryRouter: NewQueryRouter(), codespacer: sdk.NewCodespacer(), txDecoder: txDecoder, } @@ -268,6 +268,7 @@ func (app *BaseApp) FilterPeerByPubKey(info string) abci.ResponseQuery { return abci.ResponseQuery{} } +// Splits a string path using the delimter '/'. i.e. "this/is/funny" becomes []string{"this", "is", "funny"} func splitPath(requestPath string) (path []string) { path = strings.Split(requestPath, "/") // first element is empty string @@ -367,9 +368,12 @@ func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abc } func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { - // "/custom" prefix for keeper queries - querier := app.queryrouter.Route(path[1]) + // path[0] should be "custom" because "/custom" prefix is required for keeper queries. + // the queryRouter routes using path[1]. For example, in the path "custom/gov/proposal", queryRouter routes using "gov" + querier := app.queryRouter.Route(path[1]) ctx := app.checkState.ctx + // Passes the rest of the path as an argument to the querier. + // For example, in the path "custom/gov/proposal/test", the gov querier gets []string{"proposal", "test"} as the path resBytes, err := querier(ctx, path[2:], req) if err != nil { return abci.ResponseQuery{ diff --git a/baseapp/setters.go b/baseapp/setters.go index ef88b7fe5..4bcae0ed7 100644 --- a/baseapp/setters.go +++ b/baseapp/setters.go @@ -78,7 +78,7 @@ func (app *BaseApp) QueryRouter() QueryRouter { if app.sealed { panic("QueryRouter() on sealed BaseApp") } - return app.queryrouter + return app.queryRouter } func (app *BaseApp) Seal() { app.sealed = true } func (app *BaseApp) IsSealed() bool { return app.sealed } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index cf5481da8..7e5843b3d 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -3,7 +3,6 @@ package rest import ( "fmt" "net/http" - "strconv" "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" @@ -98,16 +97,13 @@ func depositHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFu return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - err := errors.Errorf("proposalID [%d] is not positive", proposalID) - w.Write([]byte(err.Error())) - + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } var req depositReq - err = buildReq(w, r, cdc, &req) + err := buildReq(w, r, cdc, &req) if err != nil { return } @@ -140,15 +136,13 @@ func voteHandlerFn(cdc *wire.Codec, cliCtx context.CLIContext) http.HandlerFunc return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - err := errors.Errorf("proposalID [%d] is not positive", proposalID) - w.Write([]byte(err.Error())) + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } var req voteReq - err = buildReq(w, r, cdc, &req) + err := buildReq(w, r, cdc, &req) if err != nil { return } @@ -181,11 +175,8 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - err := errors.Errorf("proposalID [%d] is not positive", proposalID) - w.Write([]byte(err.Error())) - + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } @@ -232,12 +223,8 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - err := errors.Errorf("proposalID [%d] is not positive", proposalID) - w.Write([]byte(err.Error())) - + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } @@ -313,12 +300,8 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - err := errors.Errorf("proposalID [%s] is not positive", proposalID) - w.Write([]byte(err.Error())) - + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } @@ -395,12 +378,8 @@ func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - proposalID, err := strconv.ParseInt(strProposalID, 10, 64) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - err := errors.Errorf("proposalID [%s] is not positive", proposalID) - w.Write([]byte(err.Error())) - + proposalID, ok := parseInt64OrReturnBadRequest(strProposalID, w) + if !ok { return } @@ -442,6 +421,7 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { strNumLatest := r.URL.Query().Get(RestNumLatest) var err error + var ok bool var voterAddr sdk.AccAddress var depositerAddr sdk.AccAddress var proposalStatus gov.ProposalStatus @@ -479,11 +459,8 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { } } if len(strNumLatest) != 0 { - numLatest, err = strconv.ParseInt(strNumLatest, 10, 64) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - err := errors.Errorf("'%s' is not a valid int64", strNumLatest) - w.Write([]byte(err.Error())) + numLatest, ok = parseInt64OrReturnBadRequest(strNumLatest, w) + if !ok { return } } diff --git a/x/gov/client/rest/util.go b/x/gov/client/rest/util.go index 58d96b591..de94a8324 100644 --- a/x/gov/client/rest/util.go +++ b/x/gov/client/rest/util.go @@ -1,8 +1,10 @@ package rest import ( + "fmt" "io/ioutil" "net/http" + "strconv" "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" @@ -100,3 +102,15 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base w.Write(output) } + +func parseInt64OrReturnBadRequest(s string, w http.ResponseWriter) (n int64, ok bool) { + var err error + n, err = strconv.ParseInt(s, 10, 64) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + err := fmt.Errorf("'%s' is not a valid int64", s) + w.Write([]byte(err.Error())) + return 0, false + } + return n, true + } \ No newline at end of file diff --git a/x/gov/depositsvotes.go b/x/gov/depositsvotes.go index 5a8b6bf24..b5c65931f 100644 --- a/x/gov/depositsvotes.go +++ b/x/gov/depositsvotes.go @@ -17,12 +17,7 @@ type Vote struct { // Returns whether 2 votes are equal func (voteA Vote) Equals(voteB Vote) bool { - if voteA.Voter.Equals(voteB.Voter) && - voteA.ProposalID == voteB.ProposalID && - voteA.Option == voteB.Option { - return true - } - return false + return voteA.Voter.Equals(voteB.Voter) && voteA.ProposalID == voteB.ProposalID && voteA.Option == voteB.Option } // Returns whether a vote is empty @@ -40,12 +35,7 @@ type Deposit struct { // Returns whether 2 deposits are equal func (depositA Deposit) Equals(depositB Deposit) bool { - if depositA.Depositer.Equals(depositB.Depositer) && - depositA.ProposalID == depositB.ProposalID && - depositA.Amount.IsEqual(depositB.Amount) { - return true - } - return false + return depositA.Depositer.Equals(depositB.Depositer) && depositA.ProposalID == depositB.ProposalID && depositA.Amount.IsEqual(depositB.Amount) } // Returns whether a deposit is empty diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 45af4b471..19d842f1f 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -198,8 +198,6 @@ func (keeper Keeper) peekCurrentProposalID(ctx sdk.Context) (proposalID int64, e return -1, ErrInvalidGenesis(keeper.codespace, "InitialProposalID never set") } keeper.cdc.MustUnmarshalBinary(bz, &proposalID) - bz = keeper.cdc.MustMarshalBinary(proposalID + 1) - store.Set(KeyNextProposalID, bz) return proposalID, nil } From 97f7b88a9fd9f4cd72e2d2c7db5593cdf0c5fde8 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Thu, 16 Aug 2018 18:35:17 -0700 Subject: [PATCH 92/97] addressed Jae's comments --- baseapp/baseapp.go | 4 ++++ baseapp/queryrouter.go | 30 ++++++++++-------------------- types/account.go | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index aadea1561..828414f1e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -370,6 +370,9 @@ func handleQueryP2P(app *BaseApp, path []string, req abci.RequestQuery) (res abc func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { // path[0] should be "custom" because "/custom" prefix is required for keeper queries. // the queryRouter routes using path[1]. For example, in the path "custom/gov/proposal", queryRouter routes using "gov" + if path[1] == "" { + sdk.ErrUnknownRequest("No route for custom query specified").QueryResult() + } querier := app.queryRouter.Route(path[1]) ctx := app.checkState.ctx // Passes the rest of the path as an argument to the querier. @@ -378,6 +381,7 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res if err != nil { return abci.ResponseQuery{ Code: uint32(err.ABCICode()), + Log: err.ABCILog(), } } return abci.ResponseQuery{ diff --git a/baseapp/queryrouter.go b/baseapp/queryrouter.go index ade071f1f..23cfad072 100644 --- a/baseapp/queryrouter.go +++ b/baseapp/queryrouter.go @@ -10,14 +10,8 @@ type QueryRouter interface { Route(path string) (h sdk.Querier) } -// map a transaction type to a handler and an initgenesis function -type queryroute struct { - r string - h sdk.Querier -} - type queryrouter struct { - routes []queryroute + routes map[string]sdk.Querier } // nolint @@ -25,27 +19,23 @@ type queryrouter struct { // TODO either make Function unexported or make return type (router) Exported func NewQueryRouter() *queryrouter { return &queryrouter{ - routes: make([]queryroute, 0), + routes: map[string]sdk.Querier{}, } } -// AddRoute - TODO add description -func (rtr *queryrouter) AddRoute(r string, h sdk.Querier) QueryRouter { +// AddRoute - Adds an sdk.Querier to the route provided. Panics on duplicate +func (rtr *queryrouter) AddRoute(r string, q sdk.Querier) QueryRouter { if !isAlphaNumeric(r) { panic("route expressions can only contain alphanumeric characters") } - rtr.routes = append(rtr.routes, queryroute{r, h}) - + if rtr.routes[r] != nil { + panic("route has already been initialized") + } + rtr.routes[r] = q return rtr } -// Route - TODO add description -// TODO handle expressive matches. +// Returns the sdk.Querier for a certain route path func (rtr *queryrouter) Route(path string) (h sdk.Querier) { - for _, route := range rtr.routes { - if route.r == path { - return route.h - } - } - return nil + return rtr.routes[path] } diff --git a/types/account.go b/types/account.go index 258a095e8..9f19c2628 100644 --- a/types/account.go +++ b/types/account.go @@ -111,13 +111,19 @@ func (bz AccAddress) Format(s fmt.State, verb rune) { // Returns boolean for whether two AccAddresses are Equal func (bz AccAddress) Equals(bz2 AccAddress) bool { + if bz.Empty() && bz2.Empty() { + return true + } return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) } // Returns boolean for whether an AccAddress is empty func (bz AccAddress) Empty() bool { + if bz == nil { + return true + } bz2 := AccAddress{} - return bz.Equals(bz2) + return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) } //__________________________________________________________ @@ -206,13 +212,19 @@ func (bz ValAddress) Format(s fmt.State, verb rune) { // Returns boolean for whether two ValAddresses are Equal func (bz ValAddress) Equals(bz2 ValAddress) bool { + if bz.Empty() && bz2.Empty() { + return true + } return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) } // Returns boolean for whether an AccAddress is empty func (bz ValAddress) Empty() bool { + if bz == nil { + return true + } bz2 := ValAddress{} - return bz.Equals(bz2) + return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) } // Bech32ifyAccPub takes AccountPubKey and returns the bech32 encoded string From 44bf69e5647890f264b49c1620635f831bd32bb3 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Fri, 17 Aug 2018 00:16:17 -0700 Subject: [PATCH 93/97] run queries against cachewrapped commit state, not checkstate --- baseapp/baseapp.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 828414f1e..365d7b31f 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -374,7 +374,11 @@ func handleQueryCustom(app *BaseApp, path []string, req abci.RequestQuery) (res sdk.ErrUnknownRequest("No route for custom query specified").QueryResult() } querier := app.queryRouter.Route(path[1]) - ctx := app.checkState.ctx + if querier == nil { + sdk.ErrUnknownRequest(fmt.Sprintf("no custom querier found for route %s", path[1])).QueryResult() + } + + ctx := sdk.NewContext(app.cms.CacheMultiStore(), app.checkState.ctx.BlockHeader(), true, app.Logger) // Passes the rest of the path as an argument to the querier. // For example, in the path "custom/gov/proposal/test", the gov querier gets []string{"proposal", "test"} as the path resBytes, err := querier(ctx, path[2:], req) From 50dd53fec3bbb7694b7addb2511f948cee90c411 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Fri, 17 Aug 2018 00:40:30 -0700 Subject: [PATCH 94/97] added tally query route to gov --- x/gov/queryable.go | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/x/gov/queryable.go b/x/gov/queryable.go index 13bdfd08d..28e32eb67 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -156,16 +156,25 @@ type QueryTallyParams struct { func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { // TODO: Dependant on #1914 - // var proposalID int64 - // err2 := keeper.cdc.UnmarshalBinary(req.Data, proposalID) - // if err2 != nil { - // return []byte{}, sdk.ErrUnknownRequest() - // } + var proposalID int64 + err2 := keeper.cdc.UnmarshalBinary(req.Data, proposalID) + if err2 != nil { + return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + } - // proposal := keeper.GetProposal(ctx, proposalID) - // if proposal == nil { - // return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) - // } - // _, tallyResult, _ := tally(ctx, keeper, proposal) - return nil, nil + proposal := keeper.GetProposal(ctx, proposalID) + if proposal == nil { + return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) + } + + if proposal.GetStatus() == StatusDepositPeriod { + return keeper.cdc.MustMarshalBinaryBare(EmptyTallyResult()), nil + } + + if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected { + return keeper.cdc.MustMarshalBinaryBare(proposal.GetTallyResult()), nil + } + + _, tallyResult, _ := tally(ctx, keeper, proposal) + return keeper.cdc.MustMarshalBinaryBare(tallyResult), nil } From 5ae20d2d511aafd89008ea43433c5366d5f12e78 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Wed, 22 Aug 2018 00:10:11 -0700 Subject: [PATCH 95/97] address Chris's comments --- baseapp/setters.go | 3 - types/account.go | 8 +-- x/gov/client/rest/rest.go | 140 +++++++++++++++++--------------------- x/gov/proposals.go | 4 ++ x/gov/queryable.go | 85 ++++++++++++++++------- 5 files changed, 129 insertions(+), 111 deletions(-) diff --git a/baseapp/setters.go b/baseapp/setters.go index 4bcae0ed7..a8b1591a7 100644 --- a/baseapp/setters.go +++ b/baseapp/setters.go @@ -75,9 +75,6 @@ func (app *BaseApp) Router() Router { return app.router } func (app *BaseApp) QueryRouter() QueryRouter { - if app.sealed { - panic("QueryRouter() on sealed BaseApp") - } return app.queryRouter } func (app *BaseApp) Seal() { app.sealed = true } diff --git a/types/account.go b/types/account.go index 9f19c2628..00076b529 100644 --- a/types/account.go +++ b/types/account.go @@ -114,7 +114,7 @@ func (bz AccAddress) Equals(bz2 AccAddress) bool { if bz.Empty() && bz2.Empty() { return true } - return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) + return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 } // Returns boolean for whether an AccAddress is empty @@ -123,7 +123,7 @@ func (bz AccAddress) Empty() bool { return true } bz2 := AccAddress{} - return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) + return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 } //__________________________________________________________ @@ -215,7 +215,7 @@ func (bz ValAddress) Equals(bz2 ValAddress) bool { if bz.Empty() && bz2.Empty() { return true } - return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) + return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 } // Returns boolean for whether an AccAddress is empty @@ -224,7 +224,7 @@ func (bz ValAddress) Empty() bool { return true } bz2 := ValAddress{} - return (bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0) + return bytes.Compare(bz.Bytes(), bz2.Bytes()) == 0 } // Bech32ifyAccPub takes AccountPubKey and returns the bech32 encoded string diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 7e5843b3d..5cdc7bda2 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -186,7 +186,14 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { ProposalID: proposalID, } - res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(params)) + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) @@ -194,18 +201,7 @@ func queryProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { return } - var proposal gov.Proposal - cdc.MustUnmarshalBinary(res, &proposal) - - output, err := wire.MarshalJSONIndent(cdc, proposal) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - - return - } - - w.Write(output) + w.Write(res) } } @@ -252,7 +248,14 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { Depositer: depositerAddr, } - res, err := cliCtx.QueryWithData("custom/gov/deposit", cdc.MustMarshalBinary(params)) + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + + res, err := cliCtx.QueryWithData("custom/gov/deposit", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) @@ -261,15 +264,7 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { } var deposit gov.Deposit - cdc.MustUnmarshalBinary(res, &deposit) - - output, err := wire.MarshalJSONIndent(cdc, deposit) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - - return - } + cdc.UnmarshalJSON(res, &deposit) if deposit.Empty() { res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) if err != nil || len(res) == 0 { @@ -283,7 +278,8 @@ func queryDepositHandlerFn(cdc *wire.Codec) http.HandlerFunc { w.Write([]byte(err.Error())) return } - w.Write(output) + + w.Write(res) } } @@ -327,8 +323,14 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { Voter: voterAddr, ProposalID: proposalID, } + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } - res, err := cliCtx.QueryWithData("custom/gov/vote", cdc.MustMarshalBinary(params)) + res, err := cliCtx.QueryWithData("custom/gov/vote", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) @@ -337,17 +339,15 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { } var vote gov.Vote - cdc.MustUnmarshalBinary(res, &vote) - - output, err := wire.MarshalJSONIndent(cdc, vote) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - - return - } + cdc.UnmarshalJSON(res, &vote) if vote.Empty() { - res, err := cliCtx.QueryWithData("custom/gov/proposal", cdc.MustMarshalBinary(gov.QueryProposalParams{params.ProposalID})) + bz, err := cdc.MarshalJSON(gov.QueryProposalParams{params.ProposalID}) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } + res, err := cliCtx.QueryWithData("custom/gov/proposal", bz) if err != nil || len(res) == 0 { w.WriteHeader(http.StatusNotFound) err := errors.Errorf("proposalID [%d] does not exist", proposalID) @@ -359,7 +359,7 @@ func queryVoteHandlerFn(cdc *wire.Codec) http.HandlerFunc { w.Write([]byte(err.Error())) return } - w.Write(output) + w.Write(res) } } @@ -388,26 +388,21 @@ func queryVotesOnProposalHandlerFn(cdc *wire.Codec) http.HandlerFunc { params := gov.QueryVotesParams{ ProposalID: proposalID, } + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return + } - res, err := cliCtx.QueryWithData("custom/gov/votes", cdc.MustMarshalBinary(params)) + res, err := cliCtx.QueryWithData("custom/gov/votes", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } - var votes []gov.Vote - cdc.MustUnmarshalBinary(res, &votes) - - output, err := wire.MarshalJSONIndent(cdc, votes) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - - return - } - - w.Write(output) + w.Write(res) } } @@ -420,25 +415,21 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { strProposalStatus := r.URL.Query().Get(RestProposalStatus) strNumLatest := r.URL.Query().Get(RestNumLatest) - var err error - var ok bool - var voterAddr sdk.AccAddress - var depositerAddr sdk.AccAddress - var proposalStatus gov.ProposalStatus - var numLatest int64 + params := gov.QueryProposalsParams{} if len(bechVoterAddr) != 0 { - voterAddr, err = sdk.AccAddressFromBech32(bechVoterAddr) + voterAddr, err := sdk.AccAddressFromBech32(bechVoterAddr) if err != nil { w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestVoter) w.Write([]byte(err.Error())) return } + params.Voter = voterAddr } if len(bechDepositerAddr) != 0 { - depositerAddr, err = sdk.AccAddressFromBech32(bechDepositerAddr) + depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr) if err != nil { w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' needs to be bech32 encoded", RestDepositer) @@ -446,10 +437,11 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { return } + params.Depositer = depositerAddr } if len(strProposalStatus) != 0 { - proposalStatus, err = gov.ProposalStatusFromString(strProposalStatus) + proposalStatus, err := gov.ProposalStatusFromString(strProposalStatus) if err != nil { w.WriteHeader(http.StatusBadRequest) err := errors.Errorf("'%s' is not a valid Proposal Status", strProposalStatus) @@ -457,24 +449,26 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { return } + params.ProposalStatus = proposalStatus } if len(strNumLatest) != 0 { - numLatest, ok = parseInt64OrReturnBadRequest(strNumLatest, w) + numLatest, ok := parseInt64OrReturnBadRequest(strNumLatest, w) if !ok { return } + params.NumLatestProposals = numLatest + } + + bz, err := cdc.MarshalJSON(params) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error())) + return } cliCtx := context.NewCLIContext().WithCodec(cdc) - params := gov.QueryProposalsParams{ - Depositer: depositerAddr, - Voter: voterAddr, - ProposalStatus: proposalStatus, - NumLatestProposals: numLatest, - } - - res, err := cliCtx.QueryWithData("custom/gov/proposals", cdc.MustMarshalBinary(params)) + res, err := cliCtx.QueryWithData("custom/gov/proposals", bz) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) @@ -482,16 +476,6 @@ func queryProposalsWithParameterFn(cdc *wire.Codec) http.HandlerFunc { return } - var matchingProposals []gov.Proposal - cdc.MustUnmarshalBinary(res, &matchingProposals) - output, err := wire.MarshalJSONIndent(cdc, matchingProposals) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(err.Error())) - - return - } - - w.Write(output) + w.Write(res) } } diff --git a/x/gov/proposals.go b/x/gov/proposals.go index f05dabd08..c52ab1e87 100644 --- a/x/gov/proposals.go +++ b/x/gov/proposals.go @@ -110,6 +110,7 @@ type ProposalKind byte //nolint const ( + ProposalTypeNil ProposalKind = 0x00 ProposalTypeText ProposalKind = 0x01 ProposalTypeParameterChange ProposalKind = 0x02 ProposalTypeSoftwareUpgrade ProposalKind = 0x03 @@ -203,6 +204,7 @@ type ProposalStatus byte //nolint const ( + StatusNil ProposalStatus = 0x00 StatusDepositPeriod ProposalStatus = 0x01 StatusVotingPeriod ProposalStatus = 0x02 StatusPassed ProposalStatus = 0x03 @@ -220,6 +222,8 @@ func ProposalStatusFromString(str string) (ProposalStatus, error) { return StatusPassed, nil case "Rejected": return StatusRejected, nil + case "": + return StatusNil, nil default: return ProposalStatus(0xff), errors.Errorf("'%s' is not a valid proposal status", str) } diff --git a/x/gov/queryable.go b/x/gov/queryable.go index 28e32eb67..e64d506d1 100644 --- a/x/gov/queryable.go +++ b/x/gov/queryable.go @@ -1,7 +1,10 @@ package gov import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" abci "github.com/tendermint/tendermint/abci/types" ) @@ -35,16 +38,21 @@ type QueryProposalParams struct { func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryProposalParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } proposal := keeper.GetProposal(ctx, params.ProposalID) if proposal == nil { return []byte{}, ErrUnknownProposal(DefaultCodespace, params.ProposalID) } - return keeper.cdc.MustMarshalBinary(proposal), nil + + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, proposal) + if err2 != nil { + panic("could not marshal result to JSON") + } + return bz, nil } // Params for query 'custom/gov/deposit' @@ -55,13 +63,17 @@ type QueryDepositParams struct { func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryDepositParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositer) - return keeper.cdc.MustMarshalBinary(deposit), nil + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, deposit) + if err2 != nil { + panic("could not marshal result to JSON") + } + return bz, nil } // Params for query 'custom/gov/vote' @@ -72,13 +84,17 @@ type QueryVoteParams struct { func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryVoteParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter) - return keeper.cdc.MustMarshalBinary(vote), nil + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, vote) + if err2 != nil { + panic("could not marshal result to JSON") + } + return bz, nil } // Params for query 'custom/gov/deposits' @@ -88,9 +104,9 @@ type QueryDepositsParams struct { func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryDepositParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } var deposits []Deposit @@ -101,7 +117,11 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper deposits = append(deposits, deposit) } - return keeper.cdc.MustMarshalBinary(deposits), nil + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, deposits) + if err2 != nil { + panic("could not marshal result to JSON") + } + return bz, nil } // Params for query 'custom/gov/votes' @@ -111,9 +131,10 @@ type QueryVotesParams struct { func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryVotesParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) + if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } var votes []Vote @@ -124,7 +145,11 @@ func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke votes = append(votes, vote) } - return keeper.cdc.MustMarshalBinary(votes), nil + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, votes) + if err2 != nil { + panic("could not marshal result to JSON") + } + return bz, nil } // Params for query 'custom/gov/proposals' @@ -137,14 +162,17 @@ type QueryProposalsParams struct { func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) { var params QueryProposalsParams - err2 := keeper.cdc.UnmarshalBinary(req.Data, ¶ms) + err2 := keeper.cdc.UnmarshalJSON(req.Data, ¶ms) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.NumLatestProposals) - bz := keeper.cdc.MustMarshalBinary(proposals) + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, proposals) + if err2 != nil { + panic("could not marshal result to JSON") + } return bz, nil } @@ -157,9 +185,9 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke // TODO: Dependant on #1914 var proposalID int64 - err2 := keeper.cdc.UnmarshalBinary(req.Data, proposalID) + err2 := keeper.cdc.UnmarshalJSON(req.Data, proposalID) if err2 != nil { - return []byte{}, sdk.ErrUnknownRequest("incorrectly formatted request data") + return []byte{}, sdk.ErrUnknownRequest(fmt.Sprintf("incorrectly formatted request data - %s", err2.Error())) } proposal := keeper.GetProposal(ctx, proposalID) @@ -167,14 +195,19 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke return []byte{}, ErrUnknownProposal(DefaultCodespace, proposalID) } + var tallyResult TallyResult + if proposal.GetStatus() == StatusDepositPeriod { - return keeper.cdc.MustMarshalBinaryBare(EmptyTallyResult()), nil + tallyResult = EmptyTallyResult() + } else if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected { + tallyResult = proposal.GetTallyResult() + } else { + _, tallyResult, _ = tally(ctx, keeper, proposal) } - if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected { - return keeper.cdc.MustMarshalBinaryBare(proposal.GetTallyResult()), nil + bz, err2 := wire.MarshalJSONIndent(keeper.cdc, tallyResult) + if err2 != nil { + panic("could not marshal result to JSON") } - - _, tallyResult, _ := tally(ctx, keeper, proposal) - return keeper.cdc.MustMarshalBinaryBare(tallyResult), nil + return bz, nil } From 7f43d3b2900652a62f365bfad5dafb4b1bdd1e8f Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal <sunnya97@gmail.com> Date: Wed, 22 Aug 2018 00:17:37 -0700 Subject: [PATCH 96/97] fixed GetLastProposalID function --- x/gov/keeper.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 19d842f1f..e8dbbc4a7 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -167,12 +167,10 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk // Get the last used proposal ID func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) { - store := ctx.KVStore(keeper.storeKey) - bz := store.Get(KeyNextProposalID) - if bz == nil { + proposalID, err := keeper.peekCurrentProposalID(ctx) + if err != nil { return 0 } - keeper.cdc.MustUnmarshalBinary(bz, &proposalID) proposalID-- return } From ba56c570c07ebf7c9c874211eaff0a6696154001 Mon Sep 17 00:00:00 2001 From: Christopher Goes <cwgoes@pluranimity.org> Date: Wed, 22 Aug 2018 12:40:15 +0200 Subject: [PATCH 97/97] Update Gopkg.lock --- Gopkg.lock | 198 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 178 insertions(+), 20 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index e94ad3ec0..73a2ff60f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,57 +2,76 @@ [[projects]] + digest = "1:09a7f74eb6bb3c0f14d8926610c87f569c5cff68e978d30e9a3540aeb626fdf0" name = "github.com/bartekn/go-bip39" packages = ["."] + pruneopts = "UT" revision = "a05967ea095d81c8fe4833776774cfaff8e5036c" [[projects]] branch = "master" + digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" name = "github.com/beorn7/perks" packages = ["quantile"] + pruneopts = "UT" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] + digest = "1:1343a2963481a305ca4d051e84bc2abd16b601ee22ed324f8d605de1adb291b0" name = "github.com/bgentry/speakeasy" packages = ["."] + pruneopts = "UT" revision = "4aabc24848ce5fd31929f7d1e4ea74d3709c14cd" version = "v0.1.0" [[projects]] branch = "master" + digest = "1:70f6b224a59b2fa453debffa85c77f71063d8754b90c8c4fbad5794e2c382b0f" name = "github.com/brejski/hid" packages = ["."] + pruneopts = "UT" revision = "06112dcfcc50a7e0e4fd06e17f9791e788fdaafc" [[projects]] branch = "master" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] + pruneopts = "UT" revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] + digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" name = "github.com/btcsuite/btcutil" packages = ["bech32"] + pruneopts = "UT" revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" [[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "UT" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" [[projects]] + digest = "1:c7644c73a3d23741fdba8a99b1464e021a224b7e205be497271a8003a15ca41b" name = "github.com/ebuchman/fail-test" packages = ["."] + pruneopts = "UT" revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" [[projects]] + digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" name = "github.com/fsnotify/fsnotify" packages = ["."] + pruneopts = "UT" revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" version = "v1.4.7" [[projects]] + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -61,24 +80,30 @@ "metrics", "metrics/discard", "metrics/internal/lv", - "metrics/prometheus" + "metrics/prometheus", ] + pruneopts = "UT" revision = "4dc7be5d2d12881735283bcab7352178e190fc71" version = "v0.6.0" [[projects]] + digest = "1:31a18dae27a29aa074515e43a443abfd2ba6deb6d69309d8d7ce789c45f34659" name = "github.com/go-logfmt/logfmt" packages = ["."] + pruneopts = "UT" revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" version = "v0.3.0" [[projects]] + digest = "1:c4a2528ccbcabf90f9f3c464a5fc9e302d592861bbfd0b7135a7de8a943d0406" name = "github.com/go-stack/stack" packages = ["."] + pruneopts = "UT" revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc" version = "v1.7.0" [[projects]] + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -86,213 +111,272 @@ "proto", "protoc-gen-gogo/descriptor", "sortkeys", - "types" + "types", ] + pruneopts = "UT" revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" [[projects]] + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp" + "ptypes/timestamp", ] + pruneopts = "UT" revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:4a0c6bb4805508a6287675fac876be2ac1182539ca8a32468d8128882e9d5009" name = "github.com/golang/snappy" packages = ["."] + pruneopts = "UT" revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a" [[projects]] + digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" name = "github.com/gorilla/context" packages = ["."] + pruneopts = "UT" revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" version = "v1.1.1" [[projects]] + digest = "1:e73f5b0152105f18bc131fba127d9949305c8693f8a762588a82a48f61756f5f" name = "github.com/gorilla/mux" packages = ["."] + pruneopts = "UT" revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" version = "v1.6.2" [[projects]] + digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e" name = "github.com/gorilla/websocket" packages = ["."] + pruneopts = "UT" revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" version = "v1.2.0" [[projects]] branch = "master" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", "json/parser", "json/scanner", - "json/token" + "json/token", ] + pruneopts = "UT" revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168" [[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "UT" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] branch = "master" + digest = "1:39b27d1381a30421f9813967a5866fba35dc1d4df43a6eefe3b7a5444cb07214" name = "github.com/jmhodges/levigo" packages = ["."] + pruneopts = "UT" revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" [[projects]] branch = "master" + digest = "1:a64e323dc06b73892e5bb5d040ced475c4645d456038333883f58934abbf6f72" name = "github.com/kr/logfmt" packages = ["."] + pruneopts = "UT" revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" [[projects]] + digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7" name = "github.com/magiconair/properties" packages = ["."] + pruneopts = "UT" revision = "c2353362d570a7bfa228149c62842019201cfb71" version = "v1.8.0" [[projects]] + digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb" name = "github.com/mattn/go-isatty" packages = ["."] + pruneopts = "UT" revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" version = "v0.0.3" [[projects]] + digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] + pruneopts = "UT" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" version = "v1.0.1" [[projects]] branch = "master" + digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" name = "github.com/mitchellh/mapstructure" packages = ["."] + pruneopts = "UT" revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] + digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" name = "github.com/pelletier/go-toml" packages = ["."] + pruneopts = "UT" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194" version = "v1.2.0" [[projects]] + digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" name = "github.com/pkg/errors" packages = ["."] + pruneopts = "UT" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "UT" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", - "prometheus/promhttp" + "prometheus/promhttp", ] + pruneopts = "UT" revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632" [[projects]] branch = "master" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] + pruneopts = "UT" revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" [[projects]] branch = "master" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model" + "model", ] + pruneopts = "UT" revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" [[projects]] branch = "master" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfs", - "xfs" + "xfs", ] + pruneopts = "UT" revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" [[projects]] + digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c" name = "github.com/rcrowley/go-metrics" packages = ["."] + pruneopts = "UT" revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", - "mem" + "mem", ] + pruneopts = "UT" revision = "787d034dfe70e44075ccc060d346146ef53270ad" version = "v1.1.1" [[projects]] + digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f" name = "github.com/spf13/cast" packages = ["."] + pruneopts = "UT" revision = "8965335b8c7107321228e3e3702cab9832751bac" version = "v1.2.0" [[projects]] + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "UT" revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" version = "v0.0.1" [[projects]] branch = "master" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] + pruneopts = "UT" revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "UT" revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" version = "v1.0.2" [[projects]] + digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" name = "github.com/spf13/viper" packages = ["."] + pruneopts = "UT" revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" version = "v1.0.0" [[projects]] + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", - "require" + "require", ] + pruneopts = "UT" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" version = "v1.2.1" [[projects]] branch = "master" + digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -306,33 +390,41 @@ "leveldb/opt", "leveldb/storage", "leveldb/table", - "leveldb/util" + "leveldb/util", ] + pruneopts = "UT" revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" [[projects]] branch = "master" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", "edwards25519", - "extra25519" + "extra25519", ] + pruneopts = "UT" revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" [[projects]] + digest = "1:e0a2a4be1e20c305badc2b0a7a9ab7fef6da500763bec23ab81df3b5f9eec9ee" name = "github.com/tendermint/go-amino" packages = ["."] + pruneopts = "UT" revision = "a8328986c1608950fa5d3d1c0472cccc4f8fc02c" version = "v0.12.0-rc0" [[projects]] + digest = "1:d4a15d404afbf591e8be16fcda7f5ac87948d5c7531f9d909fd84cc730ab16e2" name = "github.com/tendermint/iavl" packages = ["."] + pruneopts = "UT" revision = "35f66e53d9b01e83b30de68b931f54b2477a94c9" version = "v0.9.2" [[projects]] + digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -392,24 +484,30 @@ "state/txindex/kv", "state/txindex/null", "types", - "version" + "version", ] + pruneopts = "UT" revision = "013b9cef642f875634c614019ab13b17570778ad" version = "v0.23.0" [[projects]] + digest = "1:bf6d9a827ea3cad964c2f863302e4f6823170d0b5ed16f72cf1184a7c615067e" name = "github.com/tendermint/tmlibs" packages = ["cli"] + pruneopts = "UT" revision = "49596e0a1f48866603813df843c9409fc19805c6" version = "v0.9.0" [[projects]] + digest = "1:4dcb0dd65feecb068ce23a234d1a07c7868a1e39f52a6defcae0bb371d03abf6" name = "github.com/zondax/ledger-goclient" packages = ["."] + pruneopts = "UT" revision = "4296ee5701e945f9b3a7dbe51f402e0b9be57259" [[projects]] branch = "master" + digest = "1:27507554c6d4f060d8d700c31c624a43d3a92baa634e178ddc044bdf7d13b44a" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -425,11 +523,13 @@ "pbkdf2", "poly1305", "ripemd160", - "salsa20/salsa" + "salsa20/salsa", ] - revision = "aabede6cba87e37f413b3e60ebfc214f8eeca1b0" + pruneopts = "UT" + revision = "614d502a4dac94afa3a6ce146bd1736da82514c6" [[projects]] + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -439,20 +539,24 @@ "idna", "internal/timeseries", "netutil", - "trace" + "trace", ] + pruneopts = "UT" revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f" [[projects]] branch = "master" + digest = "1:a0e12bc26f317c0e2d497baf767285e1790e526e8dd46553c5a67fcbc8692157" name = "golang.org/x/sys" packages = [ "cpu", - "unix" + "unix", ] - revision = "1a700e749ce29638d0bbcb531cce1094ea096bd3" + pruneopts = "UT" + revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" [[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -468,18 +572,22 @@ "unicode/bidi", "unicode/cldr", "unicode/norm", - "unicode/rangetable" + "unicode/rangetable", ] + pruneopts = "UT" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] + pruneopts = "UT" revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4" [[projects]] + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", @@ -506,20 +614,70 @@ "stats", "status", "tap", - "transport" + "transport", ] + pruneopts = "UT" revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" version = "v1.13.0" [[projects]] + digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "UT" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "46c912cbb9fa9b2ab3529af18718edada64e59822c8a2e432aec9affa3e24f45" + input-imports = [ + "github.com/bartekn/go-bip39", + "github.com/bgentry/speakeasy", + "github.com/btcsuite/btcd/btcec", + "github.com/golang/protobuf/proto", + "github.com/gorilla/mux", + "github.com/mattn/go-isatty", + "github.com/pkg/errors", + "github.com/spf13/cobra", + "github.com/spf13/pflag", + "github.com/spf13/viper", + "github.com/stretchr/testify/assert", + "github.com/stretchr/testify/require", + "github.com/tendermint/go-amino", + "github.com/tendermint/iavl", + "github.com/tendermint/tendermint/abci/server", + "github.com/tendermint/tendermint/abci/types", + "github.com/tendermint/tendermint/cmd/tendermint/commands", + "github.com/tendermint/tendermint/config", + "github.com/tendermint/tendermint/crypto", + "github.com/tendermint/tendermint/crypto/armor", + "github.com/tendermint/tendermint/crypto/ed25519", + "github.com/tendermint/tendermint/crypto/encoding/amino", + "github.com/tendermint/tendermint/crypto/merkle", + "github.com/tendermint/tendermint/crypto/secp256k1", + "github.com/tendermint/tendermint/crypto/tmhash", + "github.com/tendermint/tendermint/crypto/xsalsa20symmetric", + "github.com/tendermint/tendermint/libs/bech32", + "github.com/tendermint/tendermint/libs/cli", + "github.com/tendermint/tendermint/libs/cli/flags", + "github.com/tendermint/tendermint/libs/common", + "github.com/tendermint/tendermint/libs/db", + "github.com/tendermint/tendermint/libs/log", + "github.com/tendermint/tendermint/node", + "github.com/tendermint/tendermint/p2p", + "github.com/tendermint/tendermint/privval", + "github.com/tendermint/tendermint/proxy", + "github.com/tendermint/tendermint/rpc/client", + "github.com/tendermint/tendermint/rpc/core/types", + "github.com/tendermint/tendermint/rpc/lib/client", + "github.com/tendermint/tendermint/rpc/lib/server", + "github.com/tendermint/tendermint/types", + "github.com/tendermint/tendermint/version", + "github.com/tendermint/tmlibs/cli", + "github.com/zondax/ledger-goclient", + "golang.org/x/crypto/blowfish", + "golang.org/x/crypto/ripemd160", + ] solver-name = "gps-cdcl" solver-version = 1