Merge remote-tracking branch 'origin/develop' into rigel/deliver-max-gas

This commit is contained in:
rigelrozanski 2018-11-22 12:34:41 -05:00
commit 0861112b70
35 changed files with 608 additions and 446 deletions

View File

@ -10,6 +10,7 @@ BREAKING CHANGES
* [cli] [\#2786](https://github.com/cosmos/cosmos-sdk/pull/2786) Fix redelegation command flow
* [cli] [\#2829](https://github.com/cosmos/cosmos-sdk/pull/2829) add-genesis-account command now validates state when adding accounts
* [cli] [\#2804](https://github.com/cosmos/cosmos-sdk/issues/2804) Check whether key exists before passing it on to `tx create-validator`.
* [cli] [\#2874](https://github.com/cosmos/cosmos-sdk/pull/2874) `gaiacli tx sign` takes an optional `--output-document` flag to support output redirection.
* Gaia
@ -17,6 +18,7 @@ BREAKING CHANGES
* [\#2752](https://github.com/cosmos/cosmos-sdk/pull/2752) Don't hardcode bondable denom.
* [\#2019](https://github.com/cosmos/cosmos-sdk/issues/2019) Cap total number of signatures. Current per-transaction limit is 7, and if that is exceeded transaction is rejected.
* [\#2801](https://github.com/cosmos/cosmos-sdk/pull/2801) Remove AppInit structure.
* [\#2798](https://github.com/cosmos/cosmos-sdk/issues/2798) Governance API has miss-spelled English word in JSON response ('depositer' -> 'depositor')
* Tendermint
@ -67,7 +69,10 @@ IMPROVEMENTS
- [types] #2776 Improve safety of `Coin` and `Coins` types. Various functions
and methods will panic when a negative amount is discovered.
- #2815 Gas unit fields changed from `int64` to `uint64`.
- #2821 Codespaces are now strings
- #2779 Introduce `ValidateBasic` to the `Tx` interface and call it in the ante
handler.
* Tendermint
- #2796 Update to go-amino 0.14.1
@ -75,6 +80,7 @@ IMPROVEMENTS
BUG FIXES
* Gaia REST API (`gaiacli advanced rest-server`)
- [gaia-lite] #2868 Added handler for governance tally endpoit
* Gaia CLI (`gaiacli`)

View File

@ -300,7 +300,8 @@ func (tx *txTest) setFailOnHandler(fail bool) {
}
// Implements Tx
func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs }
func (tx txTest) GetMsgs() []sdk.Msg { return tx.Msgs }
func (tx txTest) ValidateBasic() sdk.Error { return nil }
const (
routeMsgCounter = "msgCounter"

View File

@ -678,7 +678,7 @@ func TestDeposit(t *testing.T) {
func TestVote(t *testing.T) {
name, password := "test", "1234567890"
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
cleanup, _, operAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
defer cleanup()
// create SubmitProposal TX
@ -696,7 +696,7 @@ func TestVote(t *testing.T) {
proposal := getProposal(t, port, proposalID)
require.Equal(t, "Test", proposal.GetTitle())
// create SubmitProposal TX
// deposit
resultTx = doDeposit(t, port, seed, name, password, addr, proposalID, 5)
tests.WaitForHeight(resultTx.Height+1, port)
@ -704,13 +704,27 @@ func TestVote(t *testing.T) {
proposal = getProposal(t, port, proposalID)
require.Equal(t, gov.StatusVotingPeriod, proposal.GetStatus())
// create SubmitProposal TX
// vote
resultTx = doVote(t, port, seed, name, password, addr, proposalID)
tests.WaitForHeight(resultTx.Height+1, port)
vote := getVote(t, port, proposalID, addr)
require.Equal(t, proposalID, vote.ProposalID)
require.Equal(t, gov.OptionYes, vote.Option)
tally := getTally(t, port, proposalID)
require.Equal(t, sdk.ZeroDec(), tally.Yes, "tally should be 0 as the address is not bonded")
// create bond TX
resultTx = doDelegate(t, port, seed, name, password, addr, operAddrs[0], 60)
tests.WaitForHeight(resultTx.Height+1, port)
// vote
resultTx = doVote(t, port, seed, name, password, addr, proposalID)
tests.WaitForHeight(resultTx.Height+1, port)
tally = getTally(t, port, proposalID)
require.Equal(t, sdk.NewDec(60), tally.Yes, "tally should be equal to the amount delegated")
}
func TestUnjail(t *testing.T) {
@ -816,11 +830,11 @@ func TestProposalsQuery(t *testing.T) {
require.Equal(t, proposalID3, (proposals[2]).GetProposalID())
// Test query deposited by addr1
proposals = getProposalsFilterDepositer(t, port, addrs[0])
proposals = getProposalsFilterDepositor(t, port, addrs[0])
require.Equal(t, proposalID1, (proposals[0]).GetProposalID())
// Test query deposited by addr2
proposals = getProposalsFilterDepositer(t, port, addrs[1])
proposals = getProposalsFilterDepositor(t, port, addrs[1])
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
require.Equal(t, proposalID3, (proposals[1]).GetProposalID())
@ -834,7 +848,7 @@ func TestProposalsQuery(t *testing.T) {
require.Equal(t, proposalID3, (proposals[0]).GetProposalID())
// Test query voted and deposited by addr1
proposals = getProposalsFilterVoterDepositer(t, port, addrs[0], addrs[0])
proposals = getProposalsFilterVoterDepositor(t, port, addrs[0], addrs[0])
require.Equal(t, proposalID2, (proposals[0]).GetProposalID())
// Test query votes on Proposal 2
@ -1301,8 +1315,8 @@ func getDeposits(t *testing.T, port string, proposalID uint64) []gov.Deposit {
return deposits
}
func getDeposit(t *testing.T, port string, proposalID uint64, depositerAddr sdk.AccAddress) gov.Deposit {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositerAddr), nil)
func getDeposit(t *testing.T, port string, proposalID uint64, depositorAddr sdk.AccAddress) gov.Deposit {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/deposits/%s", proposalID, depositorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var deposit gov.Deposit
err := cdc.UnmarshalJSON([]byte(body), &deposit)
@ -1328,6 +1342,15 @@ func getVotes(t *testing.T, port string, proposalID uint64) []gov.Vote {
return votes
}
func getTally(t *testing.T, port string, proposalID uint64) gov.TallyResult {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals/%d/tally", proposalID), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var tally gov.TallyResult
err := cdc.UnmarshalJSON([]byte(body), &tally)
require.Nil(t, err)
return tally
}
func getProposalsAll(t *testing.T, port string) []gov.Proposal {
res, body := Request(t, port, "GET", "/gov/proposals", nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
@ -1338,8 +1361,8 @@ func getProposalsAll(t *testing.T, port string) []gov.Proposal {
return proposals
}
func getProposalsFilterDepositer(t *testing.T, port string, depositerAddr sdk.AccAddress) []gov.Proposal {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s", depositerAddr), nil)
func getProposalsFilterDepositor(t *testing.T, port string, depositorAddr sdk.AccAddress) []gov.Proposal {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositor=%s", depositorAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.Proposal
@ -1358,8 +1381,8 @@ func getProposalsFilterVoter(t *testing.T, port string, voterAddr sdk.AccAddress
return proposals
}
func getProposalsFilterVoterDepositer(t *testing.T, port string, voterAddr, depositerAddr sdk.AccAddress) []gov.Proposal {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositer=%s&voter=%s", depositerAddr, voterAddr), nil)
func getProposalsFilterVoterDepositor(t *testing.T, port string, voterAddr, depositorAddr sdk.AccAddress) []gov.Proposal {
res, body := Request(t, port, "GET", fmt.Sprintf("/gov/proposals?depositor=%s&voter=%s", depositorAddr, voterAddr), nil)
require.Equal(t, http.StatusOK, res.StatusCode, body)
var proposals []gov.Proposal
@ -1421,7 +1444,7 @@ func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk
// deposit on proposal
jsonStr := []byte(fmt.Sprintf(`{
"depositer": "%s",
"depositor": "%s",
"amount": [{ "denom": "%s", "amount": "%d" }],
"base_req": {
"name": "%s",

View File

@ -1226,8 +1226,8 @@ paths:
required: false
type: string
- in: query
name: depositer
description: depositer address
name: depositor
description: depositor address
required: false
type: string
- in: query
@ -1281,7 +1281,7 @@ paths:
properties:
base_req:
"$ref": "#/definitions/BaseReq"
depositer:
depositor:
"$ref": "#/definitions/Address"
amount:
type: array
@ -1321,6 +1321,29 @@ paths:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}/tally:
get:
summary: Get a proposal's tally result at the current time
description: Gets a proposal's tally result at the current time. If the proposal is pending deposits (i.e status 'DepositPeriod') it returns an empty tally result.
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
description: proposal id
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
$ref: "#/definitions/TallyResult"
400:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}/votes:
post:
summary: Vote a proposal
@ -1418,10 +1441,10 @@ paths:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}/deposits/{depositer}:
/gov/proposals/{proposalId}/deposits/{depositor}:
get:
summary: Query deposit
description: Query deposit by proposalId and depositer address
description: Query deposit by proposalId and depositor address
produces:
- application/json
tags:
@ -1433,8 +1456,8 @@ paths:
required: true
in: path
- type: string
description: Bech32 depositer address
name: depositer
description: Bech32 depositor address
name: depositor
required: true
in: path
responses:
@ -1443,7 +1466,7 @@ paths:
schema:
$ref: "#/definitions/Deposit"
400:
description: Invalid proposal id or depositer address
description: Invalid proposal id or depositor address
404:
description: Found no deposit
500:
@ -1893,16 +1916,7 @@ definitions:
proposal_status:
type: string
tally_result:
type: object
properties:
yes:
type: string
abstain:
type: string
no:
type: string
no_with_veto:
type: string
$ref: "#/definitions/TallyResult"
submit_time:
type: string
total_deposit:
@ -1920,8 +1934,23 @@ definitions:
"$ref": "#/definitions/Coin"
proposal_id:
type: integer
depositer:
depositor:
"$ref": "#/definitions/Address"
TallyResult:
type: object
properties:
yes:
type: string
example: "0.0000000000"
abstain:
type: string
example: "0.0000000000"
no:
type: string
example: "0.0000000000"
no_with_veto:
type: string
example: "0.0000000000"
Vote:
type: object
properties:

View File

@ -3,6 +3,7 @@ package utils
import (
"bytes"
"fmt"
"io"
"os"
"github.com/cosmos/cosmos-sdk/client/context"
@ -88,7 +89,7 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *
// PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout.
// Don't perform online validation or lookups if offline is true.
func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg, offline bool) (err error) {
func PrintUnsignedStdTx(w io.Writer, txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg, offline bool) (err error) {
var stdTx auth.StdTx
if offline {
stdTx, err = buildUnsignedStdTxOffline(txBldr, cliCtx, msgs)
@ -100,7 +101,7 @@ func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg
}
json, err := txBldr.Codec.MarshalJSON(stdTx)
if err == nil {
fmt.Printf("%s\n", json)
fmt.Fprintf(w, "%s\n", json)
}
return
}

View File

@ -365,7 +365,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, " 1 - Test", proposalsQuery)
deposit := executeGetDeposit(t,
fmt.Sprintf("gaiacli query gov deposit --proposal-id=1 --depositer=%s --output=json %v",
fmt.Sprintf("gaiacli query gov deposit --proposal-id=1 --depositor=%s --output=json %v",
fooAddr, flags))
require.Equal(t, int64(5), deposit.Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
@ -394,7 +394,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(15), deposits[0].Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())
deposit = executeGetDeposit(t,
fmt.Sprintf("gaiacli query gov deposit --proposal-id=1 --depositer=%s --output=json %v",
fmt.Sprintf("gaiacli query gov deposit --proposal-id=1 --depositor=%s --output=json %v",
fooAddr, flags))
require.Equal(t, int64(15), deposit.Amount.AmountOf(stakeTypes.DefaultBondDenom).Int64())

View File

@ -6,17 +6,21 @@ import (
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/stake/client/cli"
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/crypto"
tmcli "github.com/tendermint/tendermint/libs/cli"
@ -80,7 +84,13 @@ following delegation and commission default parameters:
}
// Run gaiad tx create-validator
prepareFlagsForTxCreateValidator(config, nodeID, ip, genDoc.ChainID, valPubKey)
createValidatorCmd := cli.GetCmdCreateValidator(cdc)
cliCtx, txBldr, msg, err := cli.BuildCreateValidatorMsg(
context.NewCLIContext().WithCodec(cdc),
authtxb.NewTxBuilderFromCLI().WithCodec(cdc),
)
if err != nil {
return err
}
w, err := ioutil.TempFile("", "gentx")
if err != nil {
@ -88,18 +98,19 @@ following delegation and commission default parameters:
}
unsignedGenTxFilename := w.Name()
defer os.Remove(unsignedGenTxFilename)
os.Stdout = w
if err = createValidatorCmd.RunE(nil, args); err != nil {
if err := utils.PrintUnsignedStdTx(w, txBldr, cliCtx, []sdk.Msg{msg}, true); err != nil {
return err
}
w.Close()
prepareFlagsForTxSign()
signCmd := authcmd.GetSignCommand(cdc)
if w, err = prepareOutputFile(config.RootDir, nodeID); err != nil {
outputDocument, err := makeOutputFilepath(config.RootDir, nodeID)
if err != nil {
return err
}
os.Stdout = w
viper.Set("output-document", outputDocument)
return signCmd.RunE(nil, []string{unsignedGenTxFilename})
},
}
@ -145,11 +156,10 @@ func prepareFlagsForTxSign() {
viper.Set("offline", true)
}
func prepareOutputFile(rootDir, nodeID string) (w *os.File, err error) {
func makeOutputFilepath(rootDir, nodeID string) (string, error) {
writePath := filepath.Join(rootDir, "config", "gentx")
if err = common.EnsureDir(writePath, 0700); err != nil {
return
if err := common.EnsureDir(writePath, 0700); err != nil {
return "", err
}
filename := filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID))
return os.Create(filename)
return filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID)), nil
}

View File

@ -24,10 +24,12 @@ There are three types of key representations that are used:
- Derived from account keys generated by `gaiacli keys add`
- Used to receive funds
- e.g. `cosmos15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc`
* `cosmosvaloper`
* Used to associate a validator to it's operator
* Used to invoke staking commands
* e.g. `cosmosvaloper1carzvgq3e6y3z5kz5y6gxp3wpy3qdrv928vyah`
- Used to associate a validator to it's operator
- Used to invoke staking commands
- e.g. `cosmosvaloper1carzvgq3e6y3z5kz5y6gxp3wpy3qdrv928vyah`
- `cosmospub`
- Derived from account keys generated by `gaiacli keys add`
- e.g. `cosmospub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm`
@ -72,7 +74,7 @@ View the validator pubkey for your node by typing:
gaiad tendermint show-validator
```
Note that this is the Tendermint signing key, *not* the operator key you will use in delegation transactions.
Note that this is the Tendermint signing key, _not_ the operator key you will use in delegation transactions.
::: danger Warning
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.
@ -211,7 +213,7 @@ gaiacli query stake validator <account_cosmosval>
#### 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):
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 tx stake delegate \
@ -304,7 +306,7 @@ gaiacli tx stake redelegate \
--chain-id=<chain_id>
```
Here you can also redelegate a specific `shares-amount` or a `shares-fraction` with the corresponding flags.
Here you can also redelegate a specific `shares-amount` or a `shares-fraction` with the corresponding flags.
The redelegation will be automatically completed when the unbonding period has passed.
@ -367,6 +369,7 @@ With the `pool` command you will get the values for:
##### Query Delegations To Validator
You can also query all of the delegations to a particular validator:
```bash
gaiacli query delegations-to <account_cosmosval>
```
@ -418,7 +421,7 @@ Or query all available proposals:
gaiacli query gov proposals
```
You can also query proposals filtered by `voter` or `depositer` by using the corresponding flags.
You can also query proposals filtered by `voter` or `depositor` by using the corresponding flags.
#### Increase deposit
@ -447,7 +450,7 @@ You can also query a deposit submitted by a specific address:
```bash
gaiacli query gov deposit \
--proposal-id=<proposal_id> \
--depositer=<account_cosmos>
--depositor=<account_cosmos>
```
#### Vote on a proposal

View File

@ -42,7 +42,7 @@ If proposal's deposit does not reach `MinDeposit` before `MaxDepositPeriod`, pro
There is one instance where Atom holders that deposits can be refunded:
* If the proposal is accepted.
Then, deposits will automatically be refunded to their respective depositer.
Then, deposits will automatically be refunded to their respective depositor.
### Proposal types

View File

@ -68,8 +68,8 @@ const (
```go
type Deposit struct {
Amount sdk.Coins // Amount of coins deposited by depositer
Depositer crypto.address // Address of depositer
Amount sdk.Coins // Amount of coins deposited by depositor
Depositor crypto.address // Address of depositor
}
```
@ -185,8 +185,8 @@ And the pseudocode for the `ProposalProcessingQueue`:
// proposal was accepted at the end of the voting period
// refund deposits (non-voters already punished)
proposal.CurrentStatus = ProposalStatusAccepted
for each (amount, depositer) in proposal.Deposits
depositer.AtomBalance += amount
for each (amount, depositor) in proposal.Deposits
depositor.AtomBalance += amount
else
// proposal was rejected

View File

@ -32,9 +32,12 @@ type Msg interface {
// Transactions objects must fulfill the Tx
type Tx interface {
// Gets the Msg.
// Gets the all the transaction's messages.
GetMsgs() []Msg
// ValidateBasic does a simple and lightweight validation check that doesn't
// require access to any other information.
ValidateBasic() Error
}
//__________________________________________________________

View File

@ -8,7 +8,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/multisig"
"github.com/tendermint/tendermint/crypto/secp256k1"
)
@ -67,28 +66,18 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
}
}()
err := validateBasic(stdTx)
if err != nil {
if err := tx.ValidateBasic(); err != nil {
return newCtx, err.Result(), true
}
// charge gas for the memo
newCtx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(stdTx.GetMemo())), "memo")
// stdSigs contains the sequence number, account number, and signatures
stdSigs := stdTx.GetSignatures() // When simulating, this would just be a 0-length slice.
// stdSigs contains the sequence number, account number, and signatures.
// When simulating, this would just be a 0-length slice.
stdSigs := stdTx.GetSignatures()
signerAddrs := stdTx.GetSigners()
sigCount := 0
for i := 0; i < len(stdSigs); i++ {
sigCount += countSubKeys(stdSigs[i].PubKey)
if sigCount > txSigLimit {
return newCtx, sdk.ErrTooManySignatures(fmt.Sprintf(
"signatures: %d, limit: %d", sigCount, txSigLimit),
).Result(), true
}
}
// create the list of all sign bytes
signBytesList := getSignBytesList(newCtx.ChainID(), stdTx, stdSigs)
signerAccs, res := getSignerAccs(newCtx, am, signerAddrs)
@ -129,29 +118,6 @@ func NewAnteHandler(am AccountKeeper, fck FeeCollectionKeeper) sdk.AnteHandler {
}
}
// Validate the transaction based on things that don't depend on the context
func validateBasic(tx StdTx) (err sdk.Error) {
// Assert that there are signatures.
sigs := tx.GetSignatures()
if len(sigs) == 0 {
return sdk.ErrUnauthorized("no signers")
}
// Assert that number of signatures is correct.
var signerAddrs = tx.GetSigners()
if len(sigs) != len(signerAddrs) {
return sdk.ErrUnauthorized("wrong number of signers")
}
memo := tx.GetMemo()
if len(memo) > maxMemoCharacters {
return sdk.ErrMemoTooLarge(
fmt.Sprintf("maximum number of characters is %d but received %d characters",
maxMemoCharacters, len(memo)))
}
return nil
}
func getSignerAccs(ctx sdk.Context, am AccountKeeper, addrs []sdk.AccAddress) (accs []Account, res sdk.Result) {
accs = make([]Account, len(addrs))
for i := 0; i < len(accs); i++ {
@ -340,15 +306,3 @@ func getSignBytesList(chainID string, stdTx StdTx, stdSigs []StdSignature) (sign
}
return
}
func countSubKeys(pub crypto.PubKey) int {
v, ok := pub.(*multisig.PubKeyMultisigThreshold)
if !ok {
return 1
}
nkeys := 0
for _, subkey := range v.PubKeys {
nkeys += countSubKeys(subkey)
}
return nkeys
}

View File

@ -3,9 +3,7 @@ package cli
import (
"fmt"
"io/ioutil"
"github.com/pkg/errors"
"github.com/spf13/viper"
"os"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
@ -13,7 +11,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/go-amino"
)
@ -22,6 +22,7 @@ const (
flagValidateSigs = "validate-signatures"
flagOffline = "offline"
flagSigOnly = "signature-only"
flagOutfile = "output-document"
)
// GetSignCommand returns the sign command
@ -52,6 +53,8 @@ recommended to set such parameters manually.`,
cmd.Flags().Bool(flagValidateSigs, false, "Print the addresses that must sign the transaction, "+
"those who have already signed it, and make sure that signatures are in the correct order.")
cmd.Flags().Bool(flagOffline, false, "Offline mode. Do not query local cache.")
cmd.Flags().String(flagOutfile, "",
"The document will be written to the given file instead of STDOUT")
// Add the flags here and return the command
return client.PostCommands(cmd)[0]
@ -107,7 +110,20 @@ func makeSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error
if err != nil {
return err
}
fmt.Printf("%s\n", json)
if viper.GetString(flagOutfile) == "" {
fmt.Printf("%s\n", json)
return
}
fp, err := os.OpenFile(
viper.GetString(flagOutfile), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644,
)
if err != nil {
return err
}
defer fp.Close()
fmt.Fprintf(fp, "%s\n", json)
return
}
}

View File

@ -2,10 +2,12 @@ package auth
import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/multisig"
)
var _ sdk.Tx = (*StdTx)(nil)
@ -28,11 +30,61 @@ func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdT
}
}
//nolint
// GetMsgs returns the all the transaction's messages.
func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs }
// ValidateBasic does a simple and lightweight validation check that doesn't
// require access to any other information.
func (tx StdTx) ValidateBasic() sdk.Error {
stdSigs := tx.GetSignatures()
if !tx.Fee.Amount.IsNotNegative() {
return sdk.ErrInsufficientFee(fmt.Sprintf("invalid fee %s amount provided", tx.Fee.Amount))
}
if len(stdSigs) == 0 {
return sdk.ErrUnauthorized("no signers")
}
if len(stdSigs) != len(tx.GetSigners()) {
return sdk.ErrUnauthorized("wrong number of signers")
}
if len(tx.GetMemo()) > maxMemoCharacters {
return sdk.ErrMemoTooLarge(
fmt.Sprintf(
"maximum number of characters is %d but received %d characters",
maxMemoCharacters, len(tx.GetMemo()),
),
)
}
sigCount := 0
for i := 0; i < len(stdSigs); i++ {
sigCount += countSubKeys(stdSigs[i].PubKey)
if sigCount > txSigLimit {
return sdk.ErrTooManySignatures(
fmt.Sprintf("signatures: %d, limit: %d", sigCount, txSigLimit),
)
}
}
return nil
}
func countSubKeys(pub crypto.PubKey) int {
v, ok := pub.(*multisig.PubKeyMultisigThreshold)
if !ok {
return 1
}
numKeys := 0
for _, subkey := range v.PubKeys {
numKeys += countSubKeys(subkey)
}
return numKeys
}
// GetSigners returns the addresses that must sign the transaction.
// Addresses are returned in a determistic order.
// Addresses are returned in a deterministic order.
// They are accumulated from the GetSigners method for each Msg
// in the order they appear in tx.GetMsgs().
// Duplicate addresses will be omitted.

View File

@ -2,11 +2,15 @@ package auth
import (
"fmt"
"strings"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
)
var (
@ -51,3 +55,75 @@ func TestStdSignBytes(t *testing.T) {
require.Equal(t, tc.want, got, "Got unexpected result on test case i: %d", i)
}
}
func TestTxValidateBasic(t *testing.T) {
ctx := sdk.NewContext(nil, abci.Header{ChainID: "mychainid"}, false, log.NewNopLogger())
// keys and addresses
priv1, addr1 := privAndAddr()
priv2, addr2 := privAndAddr()
priv3, addr3 := privAndAddr()
priv4, addr4 := privAndAddr()
priv5, addr5 := privAndAddr()
priv6, addr6 := privAndAddr()
priv7, addr7 := privAndAddr()
priv8, addr8 := privAndAddr()
// msg and signatures
msg1 := newTestMsg(addr1, addr2)
fee := newStdFee()
msgs := []sdk.Msg{msg1}
// require to fail validation upon invalid fee
badFee := newStdFee()
badFee.Amount[0].Amount = sdk.NewInt(-5)
tx := newTestTx(ctx, nil, nil, nil, nil, badFee)
err := tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeInsufficientFee, err.Result().Code)
// require to fail validation when no signatures exist
privs, accNums, seqs := []crypto.PrivKey{}, []int64{}, []int64{}
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeUnauthorized, err.Result().Code)
// require to fail validation when signatures do not match expected signers
privs, accNums, seqs = []crypto.PrivKey{priv1}, []int64{0, 1}, []int64{0, 0}
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeUnauthorized, err.Result().Code)
// require to fail validation when memo is too large
badMemo := strings.Repeat("bad memo", 50)
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{0, 0}
tx = newTestTxWithMemo(ctx, msgs, privs, accNums, seqs, fee, badMemo)
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeMemoTooLarge, err.Result().Code)
// require to fail validation when there are too many signatures
privs = []crypto.PrivKey{priv1, priv2, priv3, priv4, priv5, priv6, priv7, priv8}
accNums, seqs = []int64{0, 0, 0, 0, 0, 0, 0, 0}, []int64{0, 0, 0, 0, 0, 0, 0, 0}
badMsg := newTestMsg(addr1, addr2, addr3, addr4, addr5, addr6, addr7, addr8)
badMsgs := []sdk.Msg{badMsg}
tx = newTestTx(ctx, badMsgs, privs, accNums, seqs, fee)
err = tx.ValidateBasic()
require.Error(t, err)
require.Equal(t, sdk.CodeTooManySignatures, err.Result().Code)
// require to pass when above criteria are matched
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{0, 0}
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
err = tx.ValidateBasic()
require.NoError(t, err)
}

View File

@ -8,6 +8,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
bankClient "github.com/cosmos/cosmos-sdk/x/bank/client"
"os"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -66,7 +67,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
// build and sign the transaction, then broadcast to Tendermint
msg := bankClient.CreateMsg(from, to, coins)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})

View File

@ -21,10 +21,7 @@ func GetCmdQueryProposal(queryRoute string, cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryProposalParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
@ -51,21 +48,23 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
Use: "proposals",
Short: "Query proposals with optional filters",
RunE: func(cmd *cobra.Command, args []string) error {
bechDepositerAddr := viper.GetString(flagDepositer)
bechDepositorAddr := viper.GetString(flagDepositor)
bechVoterAddr := viper.GetString(flagVoter)
strProposalStatus := viper.GetString(flagStatus)
numLimit := uint64(viper.GetInt64(flagNumLimit))
params := gov.QueryProposalsParams{
Limit: numLimit,
}
var depositorAddr sdk.AccAddress
var voterAddr sdk.AccAddress
var proposalStatus gov.ProposalStatus
if len(bechDepositerAddr) != 0 {
depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr)
params := gov.NewQueryProposalsParams(proposalStatus, numLimit, voterAddr, depositorAddr)
if len(bechDepositorAddr) != 0 {
depositorAddr, err := sdk.AccAddressFromBech32(bechDepositorAddr)
if err != nil {
return err
}
params.Depositer = depositerAddr
params.Depositor = depositorAddr
}
if len(bechVoterAddr) != 0 {
@ -116,7 +115,7 @@ func GetCmdQueryProposals(queryRoute string, cdc *codec.Codec) *cobra.Command {
}
cmd.Flags().String(flagNumLimit, "", "(optional) limit to latest [number] proposals. Defaults to all proposals")
cmd.Flags().String(flagDepositer, "", "(optional) filter by proposals deposited on by depositer")
cmd.Flags().String(flagDepositor, "", "(optional) filter by proposals deposited on by depositor")
cmd.Flags().String(flagVoter, "", "(optional) filter by proposals voted on by voted")
cmd.Flags().String(flagStatus, "", "(optional) filter proposals by proposal status, status: deposit_period/voting_period/passed/rejected")
@ -138,10 +137,7 @@ func GetCmdQueryVote(queryRoute string, cdc *codec.Codec) *cobra.Command {
return err
}
params := gov.QueryVoteParams{
Voter: voterAddr,
ProposalID: proposalID,
}
params := gov.NewQueryVoteParams(proposalID, voterAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
@ -172,9 +168,7 @@ func GetCmdQueryVotes(queryRoute string, cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryVotesParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
@ -205,15 +199,12 @@ func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
depositerAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositer))
depositorAddr, err := sdk.AccAddressFromBech32(viper.GetString(flagDepositor))
if err != nil {
return err
}
params := gov.QueryDepositParams{
Depositer: depositerAddr,
ProposalID: proposalID,
}
params := gov.NewQueryDepositParams(proposalID, depositorAddr)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
@ -230,7 +221,7 @@ func GetCmdQueryDeposit(queryRoute string, cdc *codec.Codec) *cobra.Command {
}
cmd.Flags().String(flagProposalID, "", "proposalID of proposal deposited on")
cmd.Flags().String(flagDepositer, "", "bech32 depositer address")
cmd.Flags().String(flagDepositor, "", "bech32 depositor address")
return cmd
}
@ -244,9 +235,7 @@ func GetCmdQueryDeposits(queryRoute string, cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryDepositsParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err
@ -276,9 +265,7 @@ func GetCmdQueryTally(queryRoute string, cdc *codec.Codec) *cobra.Command {
cliCtx := context.NewCLIContext().WithCodec(cdc)
proposalID := uint64(viper.GetInt64(flagProposalID))
params := gov.QueryTallyParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
return err

View File

@ -2,6 +2,7 @@ package cli
import (
"fmt"
"os"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
@ -27,7 +28,7 @@ const (
flagDeposit = "deposit"
flagVoter = "voter"
flagOption = "option"
flagDepositer = "depositer"
flagDepositor = "depositor"
flagStatus = "status"
flagNumLimit = "limit"
flagProposal = "proposal"
@ -103,7 +104,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
}
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// Build and sign the transaction, then broadcast to Tendermint
@ -164,7 +165,7 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
WithCodec(cdc).
WithAccountDecoder(cdc)
depositerAddr, err := cliCtx.GetFromAddress()
depositorAddr, err := cliCtx.GetFromAddress()
if err != nil {
return err
}
@ -176,14 +177,14 @@ func GetCmdDeposit(cdc *codec.Codec) *cobra.Command {
return err
}
msg := gov.NewMsgDeposit(depositerAddr, proposalID, amount)
msg := gov.NewMsgDeposit(depositorAddr, proposalID, amount)
err = msg.ValidateBasic()
if err != nil {
return err
}
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// Build and sign the transaction, then broadcast to a Tendermint
@ -229,7 +230,7 @@ func GetCmdVote(cdc *codec.Codec) *cobra.Command {
}
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
fmt.Printf("Vote[Voter:%s,ProposalID:%d,Option:%s]",

View File

@ -20,7 +20,7 @@ import (
const (
RestParamsType = "type"
RestProposalID = "proposal-id"
RestDepositer = "depositer"
RestDepositor = "depositor"
RestVoter = "voter"
RestProposalStatus = "status"
RestNumLimit = "limit"
@ -41,7 +41,8 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec)
r.HandleFunc("/gov/proposals", queryProposalsWithParameterFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}", RestProposalID), queryProposalHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits", RestProposalID), queryDepositsHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositer), queryDepositHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/deposits/{%s}", RestProposalID, RestDepositor), queryDepositHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/tally", RestProposalID), queryTallyOnProposalHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes", RestProposalID), queryVotesOnProposalHandlerFn(cdc, cliCtx)).Methods("GET")
r.HandleFunc(fmt.Sprintf("/gov/proposals/{%s}/votes/{%s}", RestProposalID, RestVoter), queryVoteHandlerFn(cdc, cliCtx)).Methods("GET")
}
@ -57,7 +58,7 @@ type postProposalReq struct {
type depositReq struct {
BaseReq utils.BaseReq `json:"base_req"`
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
}
@ -127,7 +128,7 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
}
// create the message
msg := gov.NewMsgDeposit(req.Depositer, proposalID, req.Amount)
msg := gov.NewMsgDeposit(req.Depositor, proposalID, req.Amount)
err = msg.ValidateBasic()
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
@ -244,9 +245,7 @@ func queryDepositsHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
return
}
params := gov.QueryDepositsParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
@ -268,7 +267,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
strProposalID := vars[RestProposalID]
bechDepositerAddr := vars[RestDepositer]
bechDepositorAddr := vars[RestDepositor]
if len(strProposalID) == 0 {
err := errors.New("proposalId required but not specified")
@ -281,13 +280,13 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return
}
if len(bechDepositerAddr) == 0 {
err := errors.New("depositer address required but not specified")
if len(bechDepositorAddr) == 0 {
err := errors.New("depositor address required but not specified")
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr)
depositorAddr, err := sdk.AccAddressFromBech32(bechDepositorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
@ -295,7 +294,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
params := gov.QueryDepositParams{
ProposalID: proposalID,
Depositer: depositerAddr,
Depositor: depositorAddr,
}
bz, err := cdc.MarshalJSON(params)
@ -319,7 +318,7 @@ func queryDepositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
return
}
err = errors.Errorf("depositer [%s] did not deposit on proposalID [%d]", bechDepositerAddr, proposalID)
err = errors.Errorf("depositor [%s] did not deposit on proposalID [%d]", bechDepositorAddr, proposalID)
utils.WriteErrorResponse(w, http.StatusNotFound, err.Error())
return
}
@ -412,9 +411,8 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
return
}
params := gov.QueryVotesParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
@ -435,7 +433,7 @@ func queryVotesOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
bechVoterAddr := r.URL.Query().Get(RestVoter)
bechDepositerAddr := r.URL.Query().Get(RestDepositer)
bechDepositorAddr := r.URL.Query().Get(RestDepositor)
strProposalStatus := r.URL.Query().Get(RestProposalStatus)
strNumLimit := r.URL.Query().Get(RestNumLimit)
@ -450,13 +448,13 @@ func queryProposalsWithParameterFn(cdc *codec.Codec, cliCtx context.CLIContext)
params.Voter = voterAddr
}
if len(bechDepositerAddr) != 0 {
depositerAddr, err := sdk.AccAddressFromBech32(bechDepositerAddr)
if len(bechDepositorAddr) != 0 {
depositorAddr, err := sdk.AccAddressFromBech32(bechDepositorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
params.Depositer = depositerAddr
params.Depositor = depositorAddr
}
if len(strProposalStatus) != 0 {
@ -498,10 +496,8 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
strProposalID := vars[RestProposalID]
if len(strProposalID) == 0 {
w.WriteHeader(http.StatusBadRequest)
err := errors.New("proposalId required but not specified")
w.Write([]byte(err.Error()))
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
@ -510,20 +506,17 @@ func queryTallyOnProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext)
return
}
params := gov.QueryTallyParams{
ProposalID: proposalID,
}
params := gov.NewQueryProposalParams(proposalID)
bz, err := cdc.MarshalJSON(params)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
res, err := cliCtx.QueryWithData("custom/gov/tally", bz)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}

View File

@ -28,14 +28,14 @@ func (voteA Vote) Empty() bool {
// Deposit
type Deposit struct {
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor
ProposalID uint64 `json:"proposal_id"` // proposalID of the proposal
Amount sdk.Coins `json:"amount"` // Deposit amount
}
// Returns whether 2 deposits are equal
func (depositA Deposit) Equals(depositB Deposit) bool {
return depositA.Depositer.Equals(depositB.Depositer) && depositA.ProposalID == depositB.ProposalID && depositA.Amount.IsEqual(depositB.Amount)
return depositA.Depositor.Equals(depositB.Depositor) && depositA.ProposalID == depositB.ProposalID && depositA.Amount.IsEqual(depositB.Amount)
}
// Returns whether a deposit is empty

View File

@ -69,7 +69,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
k.setVotingParams(ctx, data.VotingParams)
k.setTallyParams(ctx, data.TallyParams)
for _, deposit := range data.Deposits {
k.setDeposit(ctx, deposit.ProposalID, deposit.Deposit.Depositer, deposit.Deposit)
k.setDeposit(ctx, deposit.ProposalID, deposit.Deposit.Depositor, deposit.Deposit)
}
for _, vote := range data.Votes {
k.setVote(ctx, vote.ProposalID, vote.Vote.Voter, vote.Vote)

View File

@ -53,7 +53,7 @@ func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitPropos
func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result {
err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositer, msg.Amount)
err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount)
if err != nil {
return err.Result()
}
@ -63,7 +63,7 @@ func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result
// TODO: Add tag for if voting period started
resTags := sdk.NewTags(
tags.Action, tags.ActionDeposit,
tags.Depositer, []byte(msg.Depositer.String()),
tags.Depositor, []byte(msg.Depositor.String()),
tags.ProposalID, proposalIDBytes,
)

View File

@ -139,7 +139,7 @@ func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
}
// Get Proposal from store by ProposalID
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositerAddr sdk.AccAddress, status ProposalStatus, numLatest uint64) []Proposal {
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositorAddr sdk.AccAddress, status ProposalStatus, numLatest uint64) []Proposal {
maxProposalID, err := keeper.peekCurrentProposalID(ctx)
if err != nil {
@ -160,8 +160,8 @@ func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddr
}
}
if depositerAddr != nil && len(depositerAddr) != 0 {
_, found := keeper.GetDeposit(ctx, proposalID, depositerAddr)
if depositorAddr != nil && len(depositorAddr) != 0 {
_, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
if !found {
continue
}
@ -340,10 +340,10 @@ func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID uint64, voterAddr sd
// =====================================================
// Deposits
// Gets the deposit of a specific depositer on a specific proposal
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress) (Deposit, bool) {
// Gets the deposit of a specific depositor on a specific proposal
func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) (Deposit, bool) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(KeyDeposit(proposalID, depositerAddr))
bz := store.Get(KeyDeposit(proposalID, depositorAddr))
if bz == nil {
return Deposit{}, false
}
@ -352,15 +352,15 @@ func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositerAdd
return deposit, true
}
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, deposit Deposit) {
func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, deposit Deposit) {
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
store.Set(KeyDeposit(proposalID, depositerAddr), bz)
store.Set(KeyDeposit(proposalID, depositorAddr), bz)
}
// Adds or updates a deposit of a specific depositer on a specific proposal
// Adds or updates a deposit of a specific depositor on a specific proposal
// Activates voting period when appropriate
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositerAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (sdk.Error, bool) {
// Checks to see if proposal exists
proposal := keeper.GetProposal(ctx, proposalID)
if proposal == nil {
@ -372,8 +372,8 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositerAdd
return ErrAlreadyFinishedProposal(keeper.codespace, proposalID), false
}
// Send coins from depositer's account to DepositedCoinsAccAddr account
_, err := keeper.ck.SendCoins(ctx, depositerAddr, DepositedCoinsAccAddr, depositAmount)
// Send coins from depositor's account to DepositedCoinsAccAddr account
_, err := keeper.ck.SendCoins(ctx, depositorAddr, DepositedCoinsAccAddr, depositAmount)
if err != nil {
return err, false
}
@ -391,13 +391,13 @@ func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositerAdd
}
// Add or update deposit object
currDeposit, found := keeper.GetDeposit(ctx, proposalID, depositerAddr)
currDeposit, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
if !found {
newDeposit := Deposit{depositerAddr, proposalID, depositAmount}
keeper.setDeposit(ctx, proposalID, depositerAddr, newDeposit)
newDeposit := Deposit{depositorAddr, proposalID, depositAmount}
keeper.setDeposit(ctx, proposalID, depositorAddr, newDeposit)
} else {
currDeposit.Amount = currDeposit.Amount.Plus(depositAmount)
keeper.setDeposit(ctx, proposalID, depositerAddr, currDeposit)
keeper.setDeposit(ctx, proposalID, depositorAddr, currDeposit)
}
return nil, activatedVotingPeriod
@ -418,7 +418,7 @@ func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID uint64) {
deposit := &Deposit{}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), deposit)
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, deposit.Depositer, deposit.Amount)
_, err := keeper.ck.SendCoins(ctx, DepositedCoinsAccAddr, deposit.Depositor, deposit.Amount)
if err != nil {
panic("should not happen")
}

View File

@ -25,8 +25,8 @@ func KeyProposal(proposalID uint64) []byte {
}
// Key for getting a specific deposit from the store
func KeyDeposit(proposalID uint64, depositerAddr sdk.AccAddress) []byte {
return []byte(fmt.Sprintf("deposits:%d:%d", proposalID, depositerAddr))
func KeyDeposit(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
return []byte(fmt.Sprintf("deposits:%d:%d", proposalID, depositorAddr))
}
// Key for getting a specific vote from the store

View File

@ -93,7 +93,7 @@ func TestDeposits(t *testing.T) {
deposit, found = keeper.GetDeposit(ctx, proposalID, addrs[0])
require.True(t, found)
require.Equal(t, fourSteak, deposit.Amount)
require.Equal(t, addrs[0], deposit.Depositer)
require.Equal(t, addrs[0], deposit.Depositor)
require.Equal(t, fourSteak, keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
require.Equal(t, addr0Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[0]))
@ -104,7 +104,7 @@ func TestDeposits(t *testing.T) {
deposit, found = keeper.GetDeposit(ctx, proposalID, addrs[0])
require.True(t, found)
require.Equal(t, fourSteak.Plus(fiveSteak), deposit.Amount)
require.Equal(t, addrs[0], deposit.Depositer)
require.Equal(t, addrs[0], deposit.Depositor)
require.Equal(t, fourSteak.Plus(fiveSteak), keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
require.Equal(t, addr0Initial.Minus(fourSteak).Minus(fiveSteak), keeper.ck.GetCoins(ctx, addrs[0]))
@ -114,7 +114,7 @@ func TestDeposits(t *testing.T) {
require.True(t, votingStarted)
deposit, found = keeper.GetDeposit(ctx, proposalID, addrs[1])
require.True(t, found)
require.Equal(t, addrs[1], deposit.Depositer)
require.Equal(t, addrs[1], deposit.Depositor)
require.Equal(t, fourSteak, deposit.Amount)
require.Equal(t, fourSteak.Plus(fiveSteak).Plus(fourSteak), keeper.GetProposal(ctx, proposalID).GetTotalDeposit())
require.Equal(t, addr1Initial.Minus(fourSteak), keeper.ck.GetCoins(ctx, addrs[1]))
@ -126,11 +126,11 @@ func TestDeposits(t *testing.T) {
depositsIterator := keeper.GetDeposits(ctx, proposalID)
require.True(t, depositsIterator.Valid())
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
require.Equal(t, addrs[0], deposit.Depositer)
require.Equal(t, addrs[0], deposit.Depositor)
require.Equal(t, fourSteak.Plus(fiveSteak), deposit.Amount)
depositsIterator.Next()
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(depositsIterator.Value(), &deposit)
require.Equal(t, addrs[1], deposit.Depositer)
require.Equal(t, addrs[1], deposit.Depositor)
require.Equal(t, fourSteak, deposit.Amount)
depositsIterator.Next()
require.False(t, depositsIterator.Valid())

View File

@ -85,14 +85,14 @@ func (msg MsgSubmitProposal) GetSigners() []sdk.AccAddress {
// MsgDeposit
type MsgDeposit struct {
ProposalID uint64 `json:"proposal_id"` // ID of the proposal
Depositer sdk.AccAddress `json:"depositer"` // Address of the depositer
Depositor sdk.AccAddress `json:"depositor"` // Address of the depositor
Amount sdk.Coins `json:"amount"` // Coins to add to the proposal's deposit
}
func NewMsgDeposit(depositer sdk.AccAddress, proposalID uint64, amount sdk.Coins) MsgDeposit {
func NewMsgDeposit(depositor sdk.AccAddress, proposalID uint64, amount sdk.Coins) MsgDeposit {
return MsgDeposit{
ProposalID: proposalID,
Depositer: depositer,
Depositor: depositor,
Amount: amount,
}
}
@ -104,8 +104,8 @@ func (msg MsgDeposit) Type() string { return "deposit" }
// Implements Msg.
func (msg MsgDeposit) ValidateBasic() sdk.Error {
if len(msg.Depositer) == 0 {
return sdk.ErrInvalidAddress(msg.Depositer.String())
if len(msg.Depositor) == 0 {
return sdk.ErrInvalidAddress(msg.Depositor.String())
}
if !msg.Amount.IsValid() {
return sdk.ErrInvalidCoins(msg.Amount.String())
@ -120,7 +120,7 @@ func (msg MsgDeposit) ValidateBasic() sdk.Error {
}
func (msg MsgDeposit) String() string {
return fmt.Sprintf("MsgDeposit{%s=>%v: %v}", msg.Depositer, msg.ProposalID, msg.Amount)
return fmt.Sprintf("MsgDeposit{%s=>%v: %v}", msg.Depositor, msg.ProposalID, msg.Amount)
}
// Implements Msg.
@ -139,7 +139,7 @@ func (msg MsgDeposit) GetSignBytes() []byte {
// Implements Msg.
func (msg MsgDeposit) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Depositer}
return []sdk.AccAddress{msg.Depositor}
}
//-----------------------------------------------------------

View File

@ -57,7 +57,7 @@ func TestMsgDeposit(t *testing.T) {
_, addrs, _, _ := mock.CreateGenAccounts(1, sdk.Coins{})
tests := []struct {
proposalID uint64
depositerAddr sdk.AccAddress
depositorAddr sdk.AccAddress
depositAmount sdk.Coins
expectPass bool
}{
@ -68,7 +68,7 @@ func TestMsgDeposit(t *testing.T) {
}
for i, tc := range tests {
msg := NewMsgDeposit(tc.depositerAddr, tc.proposalID, tc.depositAmount)
msg := NewMsgDeposit(tc.depositorAddr, tc.proposalID, tc.depositAmount)
if tc.expectPass {
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
} else {

View File

@ -25,7 +25,7 @@ const (
)
func NewQuerier(keeper Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
switch path[0] {
case QueryParams:
return queryParams(ctx, path[1:], req, keeper)
@ -49,42 +49,53 @@ func NewQuerier(keeper Keeper) sdk.Querier {
}
}
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
func queryParams(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
switch path[0] {
case ParamDeposit:
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx))
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetDepositParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
case ParamVoting:
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx))
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetVotingParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
case ParamTallying:
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx))
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, keeper.GetTallyParams(ctx))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
default:
return res, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path))
return nil, sdk.ErrUnknownRequest(fmt.Sprintf("%s is not a valid query request path", req.Path))
}
}
// Params for query 'custom/gov/proposal'
// Params for queries:
// - 'custom/gov/proposal'
// - 'custom/gov/deposits'
// - 'custom/gov/tally'
// - 'custom/gov/votes'
type QueryProposalParams struct {
ProposalID uint64
}
// creates a new instance of QueryProposalParams
func NewQueryProposalParams(proposalID uint64) QueryProposalParams {
return QueryProposalParams{
ProposalID: proposalID,
}
}
// nolint: unparam
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryProposalParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
proposal := keeper.GetProposal(ctx, params.ProposalID)
@ -92,9 +103,9 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
return nil, ErrUnknownProposal(DefaultCodespace, params.ProposalID)
}
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, proposal)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposal)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
@ -102,21 +113,29 @@ func queryProposal(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
// Params for query 'custom/gov/deposit'
type QueryDepositParams struct {
ProposalID uint64
Depositer sdk.AccAddress
Depositor sdk.AccAddress
}
// creates a new instance of QueryDepositParams
func NewQueryDepositParams(proposalID uint64, depositor sdk.AccAddress) QueryDepositParams {
return QueryDepositParams{
ProposalID: proposalID,
Depositor: depositor,
}
}
// nolint: unparam
func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
func queryDeposit(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryDepositParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositer)
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, deposit)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
deposit, _ := keeper.GetDeposit(ctx, params.ProposalID, params.Depositor)
bz, err := codec.MarshalJSONIndent(keeper.cdc, deposit)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
@ -127,33 +146,36 @@ type QueryVoteParams struct {
Voter sdk.AccAddress
}
// creates a new instance of QueryVoteParams
func NewQueryVoteParams(proposalID uint64, voter sdk.AccAddress) QueryVoteParams {
return QueryVoteParams{
ProposalID: proposalID,
Voter: voter,
}
}
// nolint: unparam
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
func queryVote(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryVoteParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
vote, _ := keeper.GetVote(ctx, params.ProposalID, params.Voter)
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, vote)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, vote)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
// Params for query 'custom/gov/deposits'
type QueryDepositsParams struct {
ProposalID uint64
}
// nolint: unparam
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryDepositsParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
var deposits []Deposit
@ -164,80 +186,19 @@ func queryDeposits(ctx sdk.Context, path []string, req abci.RequestQuery, keeper
deposits = append(deposits, deposit)
}
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, deposits)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, deposits)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
// Params for query 'custom/gov/votes'
type QueryVotesParams struct {
ProposalID uint64
}
// nolint: unparam
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryVotesParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
}
var votes []Vote
votesIterator := keeper.GetVotes(ctx, params.ProposalID)
for ; votesIterator.Valid(); votesIterator.Next() {
vote := Vote{}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
votes = append(votes, vote)
}
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, votes)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
}
return bz, nil
}
// Params for query 'custom/gov/proposals'
type QueryProposalsParams struct {
Voter sdk.AccAddress
Depositer sdk.AccAddress
ProposalStatus ProposalStatus
Limit uint64
}
// nolint: unparam
func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
var params QueryProposalsParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
}
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositer, params.ProposalStatus, params.Limit)
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, proposals)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
}
return bz, nil
}
// Params for query 'custom/gov/tally'
type QueryTallyParams struct {
ProposalID uint64
}
// nolint: unparam
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) (res []byte, err sdk.Error) {
// TODO: Dependant on #1914
var params QueryTallyParams
err2 := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err2 != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err2.Error()))
func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
proposalID := params.ProposalID
@ -254,12 +215,72 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
} else if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected {
tallyResult = proposal.GetTallyResult()
} else {
// proposal is in voting period
_, tallyResult = tally(ctx, keeper, proposal)
}
bz, err2 := codec.MarshalJSONIndent(keeper.cdc, tallyResult)
if err2 != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err2.Error()))
bz, err := codec.MarshalJSONIndent(keeper.cdc, tallyResult)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
// nolint: unparam
func queryVotes(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryProposalParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
var votes []Vote
votesIterator := keeper.GetVotes(ctx, params.ProposalID)
for ; votesIterator.Valid(); votesIterator.Next() {
vote := Vote{}
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(votesIterator.Value(), &vote)
votes = append(votes, vote)
}
bz, err := codec.MarshalJSONIndent(keeper.cdc, votes)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}
// Params for query 'custom/gov/proposals'
type QueryProposalsParams struct {
Voter sdk.AccAddress
Depositor sdk.AccAddress
ProposalStatus ProposalStatus
Limit uint64
}
// creates a new instance of QueryProposalsParams
func NewQueryProposalsParams(status ProposalStatus, limit uint64, voter, depositor sdk.AccAddress) QueryProposalsParams {
return QueryProposalsParams{
Voter: voter,
Depositor: depositor,
ProposalStatus: status,
Limit: limit,
}
}
// nolint: unparam
func queryProposals(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Keeper) ([]byte, sdk.Error) {
var params QueryProposalsParams
err := keeper.cdc.UnmarshalJSON(req.Data, &params)
if err != nil {
return nil, sdk.ErrUnknownRequest(sdk.AppendMsgToErr("incorrectly formatted request data", err.Error()))
}
proposals := keeper.GetProposalsFiltered(ctx, params.Voter, params.Depositor, params.ProposalStatus, params.Limit)
bz, err := codec.MarshalJSONIndent(keeper.cdc, proposals)
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}

View File

@ -56,9 +56,7 @@ func getQueriedParams(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier s
func getQueriedProposal(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64) Proposal {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryProposal}, "/"),
Data: cdc.MustMarshalJSON(QueryProposalParams{
ProposalID: proposalID,
}),
Data: cdc.MustMarshalJSON(NewQueryProposalParams(proposalID)),
}
bz, err := querier(ctx, []string{QueryProposal}, query)
@ -71,15 +69,10 @@ func getQueriedProposal(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier
return proposal
}
func getQueriedProposals(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, depositer, voter sdk.AccAddress, status ProposalStatus, limit uint64) []Proposal {
func getQueriedProposals(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, depositor, voter sdk.AccAddress, status ProposalStatus, limit uint64) []Proposal {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryProposals}, "/"),
Data: cdc.MustMarshalJSON(QueryProposalsParams{
Voter: voter,
Depositer: depositer,
ProposalStatus: status,
Limit: limit,
}),
Data: cdc.MustMarshalJSON(NewQueryProposalsParams(status, limit, voter, depositor)),
}
bz, err := querier(ctx, []string{QueryProposal}, query)
@ -92,13 +85,10 @@ func getQueriedProposals(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querie
return proposals
}
func getQueriedDeposit(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64, depositer sdk.AccAddress) Deposit {
func getQueriedDeposit(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64, depositor sdk.AccAddress) Deposit {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryDeposit}, "/"),
Data: cdc.MustMarshalJSON(QueryDepositParams{
ProposalID: proposalID,
Depositer: depositer,
}),
Data: cdc.MustMarshalJSON(NewQueryDepositParams(proposalID, depositor)),
}
bz, err := querier(ctx, []string{QueryDeposits}, query)
@ -114,9 +104,7 @@ func getQueriedDeposit(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier
func getQueriedDeposits(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64) []Deposit {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryDeposits}, "/"),
Data: cdc.MustMarshalJSON(QueryDepositsParams{
ProposalID: proposalID,
}),
Data: cdc.MustMarshalJSON(NewQueryProposalParams(proposalID)),
}
bz, err := querier(ctx, []string{QueryDeposits}, query)
@ -132,10 +120,7 @@ func getQueriedDeposits(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier
func getQueriedVote(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64, voter sdk.AccAddress) Vote {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryVote}, "/"),
Data: cdc.MustMarshalJSON(QueryVoteParams{
ProposalID: proposalID,
Voter: voter,
}),
Data: cdc.MustMarshalJSON(NewQueryVoteParams(proposalID, voter)),
}
bz, err := querier(ctx, []string{QueryVote}, query)
@ -151,9 +136,7 @@ func getQueriedVote(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk
func getQueriedVotes(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64) []Vote {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryVote}, "/"),
Data: cdc.MustMarshalJSON(QueryVotesParams{
ProposalID: proposalID,
}),
Data: cdc.MustMarshalJSON(NewQueryProposalParams(proposalID)),
}
bz, err := querier(ctx, []string{QueryVotes}, query)
@ -169,9 +152,7 @@ func getQueriedVotes(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sd
func getQueriedTally(t *testing.T, ctx sdk.Context, cdc *codec.Codec, querier sdk.Querier, proposalID uint64) TallyResult {
query := abci.RequestQuery{
Path: strings.Join([]string{"custom", "gov", QueryTally}, "/"),
Data: cdc.MustMarshalJSON(QueryTallyParams{
ProposalID: proposalID,
}),
Data: cdc.MustMarshalJSON(NewQueryProposalParams(proposalID)),
}
bz, err := querier(ctx, []string{QueryTally}, query)

View File

@ -17,6 +17,6 @@ var (
Proposer = "proposer"
ProposalID = "proposal-id"
VotingPeriodStart = "voting-period-start"
Depositer = "depositer"
Depositor = "depositor"
Voter = "voter"
)

View File

@ -2,6 +2,7 @@ package cli
import (
"encoding/hex"
"os"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
@ -41,7 +42,7 @@ func IBCTransferCmd(cdc *codec.Codec) *cobra.Command {
return err
}
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})

View File

@ -7,6 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/slashing"
"os"
"github.com/spf13/cobra"
)
@ -30,7 +31,7 @@ func GetCmdUnjail(cdc *codec.Codec) *cobra.Command {
msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr))
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
},

View File

@ -2,6 +2,7 @@ package cli
import (
"fmt"
"os"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
@ -26,76 +27,13 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
WithCodec(cdc).
WithAccountDecoder(cdc)
amounstStr := viper.GetString(FlagAmount)
if amounstStr == "" {
return fmt.Errorf("Must specify amount to stake using --amount")
}
amount, err := sdk.ParseCoin(amounstStr)
cliCtx, txBldr, msg, err := BuildCreateValidatorMsg(cliCtx, txBldr)
if err != nil {
return err
}
valAddr, err := cliCtx.GetFromAddress()
if err != nil {
return err
}
pkStr := viper.GetString(FlagPubKey)
if len(pkStr) == 0 {
return fmt.Errorf("must use --pubkey flag")
}
pk, err := sdk.GetConsPubKeyBech32(pkStr)
if err != nil {
return err
}
if viper.GetString(FlagMoniker) == "" {
return fmt.Errorf("please enter a moniker for the validator using --moniker")
}
description := stake.Description{
Moniker: viper.GetString(FlagMoniker),
Identity: viper.GetString(FlagIdentity),
Website: viper.GetString(FlagWebsite),
Details: viper.GetString(FlagDetails),
}
// get the initial validator commission parameters
rateStr := viper.GetString(FlagCommissionRate)
maxRateStr := viper.GetString(FlagCommissionMaxRate)
maxChangeRateStr := viper.GetString(FlagCommissionMaxChangeRate)
commissionMsg, err := buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr)
if err != nil {
return err
}
var msg sdk.Msg
if viper.GetString(FlagAddressDelegator) != "" {
delAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator))
if err != nil {
return err
}
msg = stake.NewMsgCreateValidatorOnBehalfOf(
delAddr, sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
)
} else {
msg = stake.NewMsgCreateValidator(
sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
)
}
if viper.GetBool(FlagGenesisFormat) {
ip := viper.GetString(FlagIP)
nodeID := viper.GetString(FlagNodeID)
if nodeID != "" && ip != "" {
txBldr = txBldr.WithMemo(fmt.Sprintf("%s@%s:26656", nodeID, ip))
}
}
if viper.GetBool(FlagGenesisFormat) || cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, true)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, true)
}
// build and sign the transaction, then broadcast to Tendermint
@ -112,6 +50,9 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
cmd.Flags().String(FlagIP, "", fmt.Sprintf("Node's public IP. It takes effect only when used in combination with --%s", FlagGenesisFormat))
cmd.Flags().String(FlagNodeID, "", "Node's ID")
cmd.MarkFlagRequired(client.FlagFrom)
cmd.MarkFlagRequired(FlagAmount)
cmd.MarkFlagRequired(FlagPubKey)
cmd.MarkFlagRequired(FlagMoniker)
return cmd
}
@ -154,7 +95,7 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// build and sign the transaction, then broadcast to Tendermint
@ -197,7 +138,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
msg := stake.NewMsgDelegate(delAddr, valAddr, amount)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// build and sign the transaction, then broadcast to Tendermint
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
@ -252,7 +193,7 @@ func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
msg := stake.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, sharesAmount)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// build and sign the transaction, then broadcast to Tendermint
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
@ -300,7 +241,7 @@ func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
msg := stake.NewMsgBeginUnbonding(delAddr, valAddr, sharesAmount)
if cliCtx.GenerateOnly {
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}, false)
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
}
// build and sign the transaction, then broadcast to Tendermint
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
@ -312,3 +253,64 @@ func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
return cmd
}
// BuildCreateValidatorMsg makes a new MsgCreateValidator.
func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr authtxb.TxBuilder) (context.CLIContext, authtxb.TxBuilder, sdk.Msg, error) {
amounstStr := viper.GetString(FlagAmount)
amount, err := sdk.ParseCoin(amounstStr)
if err != nil {
return cliCtx, txBldr, nil, err
}
valAddr, err := cliCtx.GetFromAddress()
if err != nil {
return cliCtx, txBldr, nil, err
}
pkStr := viper.GetString(FlagPubKey)
pk, err := sdk.GetConsPubKeyBech32(pkStr)
if err != nil {
return cliCtx, txBldr, nil, err
}
description := stake.NewDescription(
viper.GetString(FlagMoniker),
viper.GetString(FlagIdentity),
viper.GetString(FlagWebsite),
viper.GetString(FlagDetails),
)
// get the initial validator commission parameters
rateStr := viper.GetString(FlagCommissionRate)
maxRateStr := viper.GetString(FlagCommissionMaxRate)
maxChangeRateStr := viper.GetString(FlagCommissionMaxChangeRate)
commissionMsg, err := buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr)
if err != nil {
return cliCtx, txBldr, nil, err
}
var msg sdk.Msg
if viper.GetString(FlagAddressDelegator) != "" {
delAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator))
if err != nil {
return cliCtx, txBldr, nil, err
}
msg = stake.NewMsgCreateValidatorOnBehalfOf(
delAddr, sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
)
} else {
msg = stake.NewMsgCreateValidator(
sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
)
}
if viper.GetBool(FlagGenesisFormat) {
ip := viper.GetString(FlagIP)
nodeID := viper.GetString(FlagNodeID)
if nodeID != "" && ip != "" {
txBldr = txBldr.WithMemo(fmt.Sprintf("%s@%s:26656", nodeID, ip))
}
}
return cliCtx, txBldr, msg, nil
}