Merge branch 'develop' into jack/dry-rest-tests

This commit is contained in:
Jack Zampolin 2018-12-11 08:44:28 -08:00 committed by GitHub
commit 73efc3c5d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 573 additions and 527 deletions

View File

@ -178,7 +178,7 @@ jobs:
name: Test multi-seed Gaia simulation
command: |
export PATH="$GOBIN:$PATH"
make test_sim_gaia_multi_seed
scripts/multisim.sh 25 TestFullGaiaSimulation
test_cover:
<<: *defaults

View File

@ -3,7 +3,8 @@
BREAKING CHANGES
* Gaia REST API (`gaiacli advanced rest-server`)
* [\#3056](https://github.com/cosmos/cosmos-sdk/pull/3056) `generate_only` and `simulate` have moved from query arguments to POST requests body.
* [gaia-lite] [\#2191](https://github.com/cosmos/cosmos-sdk/issues/2191) Split `POST /stake/delegators/{delegatorAddr}/delegations` into `POST /stake/delegators/{delegatorAddr}/delegations`, `POST /stake/delegators/{delegatorAddr}/unbonding_delegations` and `POST /stake/delegators/{delegatorAddr}/redelegations`
* [gaia-lite] [\#3056](https://github.com/cosmos/cosmos-sdk/pull/3056) `generate_only` and `simulate` have moved from query arguments to POST requests body.
* Gaia CLI (`gaiacli`)
@ -34,6 +35,8 @@ IMPROVEMENTS
* Gaia CLI (`gaiacli`)
* Gaia
* [\#3021](https://github.com/cosmos/cosmos-sdk/pull/3021) Add `--gentx-dir` to `gaiad collect-gentxs` to specify a directory from which collect and load gentxs.
Add `--output-document` to `gaiad init` to allow one to redirect output to file.
* SDK

View File

@ -47,7 +47,7 @@ type CLIContext struct {
JSON bool
PrintResponse bool
Verifier tmlite.Verifier
DryRun bool
Simulate bool
GenerateOnly bool
fromAddress types.AccAddress
fromName string
@ -85,7 +85,7 @@ func NewCLIContext() CLIContext {
JSON: viper.GetBool(client.FlagJson),
PrintResponse: viper.GetBool(client.FlagPrintResponse),
Verifier: verifier,
DryRun: viper.GetBool(client.FlagDryRun),
Simulate: viper.GetBool(client.FlagDryRun),
GenerateOnly: viper.GetBool(client.FlagGenerateOnly),
fromAddress: fromAddress,
fromName: fromName,
@ -244,3 +244,15 @@ func (ctx CLIContext) WithVerifier(verifier tmlite.Verifier) CLIContext {
ctx.Verifier = verifier
return ctx
}
// WithGenerateOnly returns a copy of the context with updated GenerateOnly value
func (ctx CLIContext) WithGenerateOnly(generateOnly bool) CLIContext {
ctx.GenerateOnly = generateOnly
return ctx
}
// WithSimulation returns a copy of the context with updated Simulate value
func (ctx CLIContext) WithSimulation(simulate bool) CLIContext {
ctx.Simulate = simulate
return ctx
}

View File

@ -43,6 +43,7 @@ const (
FlagSSLHosts = "ssl-hosts"
FlagSSLCertFile = "ssl-certfile"
FlagSSLKeyFile = "ssl-keyfile"
FlagOutputDocument = "output-document" // inspired by wget -O
)
// LineBreak can be included in a command list to provide a blank line

View File

@ -814,4 +814,4 @@ func TestProposalsQuery(t *testing.T) {
require.Len(t, votes, 2)
require.True(t, addrs[0].String() == votes[0].Voter.String() || addrs[0].String() == votes[1].Voter.String())
require.True(t, addrs[1].String() == votes[0].Voter.String() || addrs[1].String() == votes[1].Voter.String())
}
}

View File

@ -625,71 +625,6 @@ paths:
description: Bech32 AccAddress of Delegator
required: true
type: string
post:
summary: Submit delegation
parameters:
- in: body
name: delegation
description: The password of the account to remove from the KMS
schema:
type: object
properties:
base_req:
"$ref": "#/definitions/BaseReq"
delegations:
type: array
items:
type: object
properties:
delegator_addr:
$ref: "#/definitions/Address"
validator_addr:
$ref: "#/definitions/ValidatorAddress"
delegation:
$ref: "#/definitions/Coin"
begin_unbondings:
type: array
items:
type: object
properties:
delegator_addr:
$ref: "#/definitions/Address"
validator_addr:
$ref: "#/definitions/ValidatorAddress"
shares:
type: string
example: "100"
begin_redelegates:
type: array
items:
type: object
properties:
delegator_addr:
$ref: "#/definitions/Address"
validator_src_addr:
$ref: "#/definitions/ValidatorAddress"
validator_dst_addr:
$ref: "#/definitions/ValidatorAddress"
shares:
type: string
example: "100"
tags:
- ICS21
consumes:
- application/json
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid delegator address or delegation body
401:
description: Key password is wrong
500:
description: Internal Server Error
get:
summary: Get all delegations from a delegator
tags:
@ -702,12 +637,72 @@ paths:
schema:
type: array
items:
type: object
"$ref": "#/definitions/Delegation"
$ref: "#/definitions/Delegation"
400:
description: Invalid delegator address
500:
description: Internal Server Error
post:
summary: Submit delegation
parameters:
- in: body
name: delegation
description: The password of the account to remove from the KMS
schema:
type: object
properties:
base_req:
$ref: "#/definitions/BaseReq"
delegator_addr:
$ref: "#/definitions/Address"
validator_addr:
$ref: "#/definitions/ValidatorAddress"
delegation:
$ref: "#/definitions/Coin"
tags:
- ICS21
consumes:
- application/json
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid delegator address or delegation request body
401:
description: Key password is wrong
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/delegations/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Query the current delegation between a delegator and a validator
tags:
- ICS21
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/Delegation"
400:
description: Invalid delegator address or validator address
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/unbonding_delegations:
parameters:
- in: path
@ -727,12 +722,85 @@ paths:
schema:
type: array
items:
type: object
"$ref": "#/definitions/UnbondingDelegation"
$ref: "#/definitions/UnbondingDelegation"
400:
description: Invalid delegator address
500:
description: Internal Server Error
post:
summary: Submit an unbonding delegation
parameters:
- in: query
name: simulate
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
required: false
type: boolean
- in: query
name: generate_only
description: if true, build an unsigned transaction and write it back
required: false
type: boolean
- in: body
name: delegation
description: The password of the account to remove from the KMS
schema:
type: object
properties:
base_req:
$ref: "#/definitions/BaseReq"
delegator_addr:
$ref: "#/definitions/Address"
validator_addr:
$ref: "#/definitions/ValidatorAddress"
shares:
type: string
example: "100"
tags:
- ICS21
consumes:
- application/json
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid delegator address or unbonding delegation request body
401:
description: Key password is wrong
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Query all unbonding delegations between a delegator and a validator
tags:
- ICS21
produces:
- application/json
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/UnbondingDelegation"
400:
description: Invalid delegator address or validator address
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/redelegations:
parameters:
- in: path
@ -752,12 +820,58 @@ paths:
schema:
type: array
items:
type: object
"$ref": "#/definitions/Redelegation"
$ref: "#/definitions/Redelegation"
400:
description: Invalid delegator address
500:
description: Internal Server Error
post:
summary: Submit a redelegation
parameters:
- in: query
name: simulate
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
required: false
type: boolean
- in: query
name: generate_only
description: if true, build an unsigned transaction and write it back
required: false
type: boolean
- in: body
name: delegation
description: The password of the account to remove from the KMS
schema:
type: object
properties:
base_req:
$ref: "#/definitions/BaseReq"
delegator_addr:
$ref: "#/definitions/Address"
validator_src_addr:
$ref: "#/definitions/ValidatorAddress"
validator_dst_addr:
$ref: "#/definitions/ValidatorAddress"
shares:
type: string
example: "100"
tags:
- ICS21
consumes:
- application/json
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid delegator address or redelegation request body
401:
description: Key password is wrong
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/validators:
parameters:
- in: path
@ -835,63 +949,6 @@ paths:
description: Invalid delegator address
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/delegations/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Query the current delegation between a delegator and a validator
tags:
- ICS21
produces:
- application/json
responses:
200:
description: OK
schema:
$ref: "#/definitions/Delegation"
400:
description: Invalid delegator address or validator address
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 OperatorAddress of validator
required: true
type: string
get:
summary: Query all unbonding delegations between a delegator and a validator
tags:
- ICS21
produces:
- application/json
responses:
200:
description: OK
schema:
type: array
items:
type: object
"$ref": "#/definitions/UnbondingDelegation"
400:
description: Invalid delegator address or validator address
500:
description: Internal Server Error
/stake/validators:
get:
summary: Get all validator candidates
@ -1116,7 +1173,7 @@ paths:
type: object
properties:
base_req:
"$ref": "#/definitions/BaseReq"
$ref: "#/definitions/BaseReq"
responses:
200:
description: OK
@ -1147,7 +1204,7 @@ paths:
type: object
properties:
base_req:
"$ref": "#/definitions/BaseReq"
$ref: "#/definitions/BaseReq"
title:
type: string
description:
@ -1156,7 +1213,7 @@ paths:
type: string
example: "text"
proposer:
"$ref": "#/definitions/Address"
$ref: "#/definitions/Address"
initial_deposit:
type: array
items:
@ -1165,7 +1222,7 @@ paths:
200:
description: OK
schema:
"$ref": "#/definitions/BroadcastTxCommitResult"
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid proposal body
401:
@ -1201,12 +1258,57 @@ paths:
schema:
type: array
items:
"$ref": "#/definitions/TextProposal"
$ref: "#/definitions/TextProposal"
400:
description: Invalid query parameters
500:
description: Internal Server Error
/gov/proposals/{proposalId}:
get:
summary: Query a proposal
description: Query a proposal by id
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
$ref: "#/definitions/TextProposal"
400:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}/deposits:
get:
summary: Query deposits
description: Query deposits by proposalId
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/Deposit"
400:
description: Invalid proposal id
500:
description: Internal Server Error
post:
summary: Deposit tokens to a proposal
description: Send transaction to deposit tokens to a proposal
@ -1230,9 +1332,9 @@ paths:
type: object
properties:
base_req:
"$ref": "#/definitions/BaseReq"
$ref: "#/definitions/BaseReq"
depositor:
"$ref": "#/definitions/Address"
$ref: "#/definitions/Address"
amount:
type: array
items:
@ -1241,146 +1343,13 @@ paths:
200:
description: OK
schema:
"$ref": "#/definitions/BroadcastTxCommitResult"
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid proposal id or deposit body
401:
description: Key password is wrong
500:
description: Internal Server Error
get:
summary: Query deposits
description: Query deposits by proposalId
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
type: array
items:
"$ref": "#/definitions/Deposit"
400:
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
description: Send transaction to vote a proposal
consumes:
- application/json
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
description: proposal id
name: proposalId
required: true
in: path
- description: valid value of `"option"` field can be `"yes"`, `"no"`, `"no_with_veto"` and `"abstain"`
name: post_vote_body
in: body
required: true
schema:
type: object
properties:
base_req:
"$ref": "#/definitions/BaseReq"
voter:
"$ref": "#/definitions/Address"
option:
type: string
example: "yes"
responses:
200:
description: OK
schema:
"$ref": "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid proposal id or vote body
401:
description: Key password is wrong
500:
description: Internal Server Error
get:
summary: Query voters
description: Query voters information by proposalId
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
description: proposal id
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
type: array
items:
"$ref": "#/definitions/Vote"
400:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}:
get:
summary: Query a proposal
description: Query a proposal by id
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
"$ref": "#/definitions/TextProposal"
400:
description: Invalid proposal id
500:
description: Internal Server Error
/gov/proposals/{proposalId}/deposits/{depositor}:
get:
summary: Query deposit
@ -1411,6 +1380,71 @@ paths:
description: Found no deposit
500:
description: Internal Server Error
/gov/proposals/{proposalId}/votes:
get:
summary: Query voters
description: Query voters information by proposalId
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
description: proposal id
name: proposalId
required: true
in: path
responses:
200:
description: OK
schema:
type: array
items:
$ref: "#/definitions/Vote"
400:
description: Invalid proposal id
500:
description: Internal Server Error
post:
summary: Vote a proposal
description: Send transaction to vote a proposal
consumes:
- application/json
produces:
- application/json
tags:
- ICS22
parameters:
- type: string
description: proposal id
name: proposalId
required: true
in: path
- description: valid value of `"option"` field can be `"yes"`, `"no"`, `"no_with_veto"` and `"abstain"`
name: post_vote_body
in: body
required: true
schema:
type: object
properties:
base_req:
$ref: "#/definitions/BaseReq"
voter:
$ref: "#/definitions/Address"
option:
type: string
example: "yes"
responses:
200:
description: OK
schema:
$ref: "#/definitions/BroadcastTxCommitResult"
400:
description: Invalid proposal id or vote body
401:
description: Key password is wrong
500:
description: Internal Server Error
/gov/proposals/{proposalId}/votes/{voter}:
get:
summary: Query vote
@ -1441,6 +1475,29 @@ paths:
description: Found no vote
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/parameters/deposit:
get:
summary: Query governance deposit parameters
@ -1538,7 +1595,7 @@ definitions:
tags:
type: array
items:
"$ref": "#/definitions/KVPair"
$ref: "#/definitions/KVPair"
example:
code: 0
data: data
@ -1567,7 +1624,7 @@ definitions:
tags:
type: array
items:
"$ref": "#/definitions/KVPair"
$ref: "#/definitions/KVPair"
example:
code: 5
data: data
@ -1868,7 +1925,7 @@ definitions:
total_deposit:
type: array
items:
"$ref": "#/definitions/Coin"
$ref: "#/definitions/Coin"
voting_start_time:
type: string
Deposit:
@ -1877,11 +1934,11 @@ definitions:
amount:
type: array
items:
"$ref": "#/definitions/Coin"
$ref: "#/definitions/Coin"
proposal_id:
type: integer
depositor:
"$ref": "#/definitions/Address"
$ref: "#/definitions/Address"
TallyResult:
type: object
properties:

View File

@ -159,21 +159,21 @@ func ReadRESTReq(w http.ResponseWriter, r *http.Request, cdc *codec.Codec, req i
// ValidateBasic performs basic validation of a BaseReq. If custom validation
// logic is needed, the implementing request handler should perform those
// checks manually.
func (br BaseReq) ValidateBasic(w http.ResponseWriter) bool {
switch {
case len(br.Name) == 0:
func (br BaseReq) ValidateBasic(w http.ResponseWriter, cliCtx context.CLIContext) bool {
if !cliCtx.GenerateOnly && !cliCtx.Simulate {
switch {
case len(br.Password) == 0:
WriteErrorResponse(w, http.StatusUnauthorized, "password required but not specified")
return false
case len(br.ChainID) == 0:
WriteErrorResponse(w, http.StatusUnauthorized, "chain-id required but not specified")
return false
}
}
if len(br.Name) == 0 {
WriteErrorResponse(w, http.StatusUnauthorized, "name required but not specified")
return false
case len(br.Password) == 0:
WriteErrorResponse(w, http.StatusUnauthorized, "password required but not specified")
return false
case len(br.ChainID) == 0:
WriteErrorResponse(w, http.StatusUnauthorized, "chainID required but not specified")
return false
}
return true
}

View File

@ -34,14 +34,14 @@ func CompleteAndBroadcastTxCli(txBldr authtxb.TxBuilder, cliCtx context.CLIConte
return err
}
if txBldr.SimulateGas || cliCtx.DryRun {
if txBldr.SimulateGas || cliCtx.Simulate {
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, name, msgs)
if err != nil {
return err
}
fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas)
}
if cliCtx.DryRun {
if cliCtx.Simulate {
return nil
}

View File

@ -645,6 +645,37 @@ trust_node = true
cleanupDirs(gaiadHome, gaiacliHome)
}
func TestGaiadCollectGentxs(t *testing.T) {
t.Parallel()
// Initialise temporary directories
gaiadHome, gaiacliHome := getTestingHomeDirs(t.Name())
gentxDir, err := ioutil.TempDir("", "")
gentxDoc := filepath.Join(gentxDir, "gentx.json")
require.NoError(t, err)
tests.ExecuteT(t, fmt.Sprintf("gaiad --home=%s unsafe-reset-all", gaiadHome), "")
os.RemoveAll(filepath.Join(gaiadHome, "config", "gentx"))
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWrite(t, fmt.Sprintf("gaiacli keys delete --home=%s bar", gaiacliHome), app.DefaultKeyPass)
executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s foo", gaiacliHome), app.DefaultKeyPass)
executeWriteCheckErr(t, fmt.Sprintf("gaiacli keys add --home=%s bar", gaiacliHome), app.DefaultKeyPass)
executeWriteCheckErr(t, fmt.Sprintf("gaiacli config --home=%s output json", gaiacliHome))
fooAddr, _ := executeGetAddrPK(t, fmt.Sprintf("gaiacli keys show foo --home=%s", gaiacliHome))
// Run init
_ = executeInit(t, fmt.Sprintf("gaiad init -o --moniker=foo --home=%s", gaiadHome))
// Add account to genesis.json
executeWriteCheckErr(t, fmt.Sprintf(
"gaiad add-genesis-account %s 150%s,1000fooToken --home=%s", fooAddr, stakeTypes.DefaultBondDenom, gaiadHome))
executeWrite(t, fmt.Sprintf("cat %s%sconfig%sgenesis.json", gaiadHome, string(os.PathSeparator), string(os.PathSeparator)))
// Write gentx file
executeWriteCheckErr(t, fmt.Sprintf(
"gaiad gentx --name=foo --home=%s --home-client=%s --output-document=%s", gaiadHome, gaiacliHome, gentxDoc), app.DefaultKeyPass)
// Collect gentxs from a custom directory
executeWriteCheckErr(t, fmt.Sprintf("gaiad collect-gentxs --home=%s --gentx-dir=%s", gaiadHome, gentxDir), app.DefaultKeyPass)
cleanupDirs(gaiadHome, gaiacliHome, gentxDir)
}
//___________________________________________________________________________________
// helper methods

View File

@ -18,6 +18,10 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
)
const (
flagGenTxDir = "gentx-dir"
)
type initConfig struct {
ChainID string
GenTxsDir string
@ -35,7 +39,6 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
name := viper.GetString(client.FlagName)
nodeID, valPubKey, err := InitializeNodeValidatorFiles(config)
if err != nil {
return err
@ -46,19 +49,13 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
return err
}
toPrint := printInfo{
Moniker: config.Moniker,
ChainID: genDoc.ChainID,
NodeID: nodeID,
genTxsDir := viper.GetString(flagGenTxDir)
if genTxsDir == "" {
genTxsDir = filepath.Join(config.RootDir, "config", "gentx")
}
initCfg := initConfig{
ChainID: genDoc.ChainID,
GenTxsDir: filepath.Join(config.RootDir, "config", "gentx"),
Name: name,
NodeID: nodeID,
ValPubKey: valPubKey,
}
toPrint := newPrintInfo(config.Moniker, genDoc.ChainID, nodeID, genTxsDir, json.RawMessage(""))
initCfg := newInitConfig(genDoc.ChainID, genTxsDir, name, nodeID, valPubKey)
appMessage, err := genAppStateFromConfig(cdc, config, initCfg, genDoc)
if err != nil {
@ -73,6 +70,9 @@ func CollectGenTxsCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
}
cmd.Flags().String(cli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagGenTxDir, "",
"override default \"gentx\" directory from which collect and execute "+
"genesis transactions; default [--home]/config/gentx/")
return cmd
}
@ -117,3 +117,27 @@ func genAppStateFromConfig(
err = ExportGenesisFile(genFile, initCfg.ChainID, nil, appState)
return
}
func newInitConfig(chainID, genTxsDir, name, nodeID string,
valPubKey crypto.PubKey) initConfig {
return initConfig{
ChainID: chainID,
GenTxsDir: genTxsDir,
Name: name,
NodeID: nodeID,
ValPubKey: valPubKey,
}
}
func newPrintInfo(moniker, chainID, nodeID, genTxsDir string,
appMessage json.RawMessage) printInfo {
return printInfo{
Moniker: moniker,
ChainID: chainID,
NodeID: nodeID,
GenTxsDir: genTxsDir,
AppMessage: appMessage,
}
}

View File

@ -137,9 +137,12 @@ following delegation and commission default parameters:
}
// Fetch output file name
outputDocument, err := makeOutputFilepath(config.RootDir, nodeID)
if err != nil {
return err
outputDocument := viper.GetString(client.FlagOutputDocument)
if outputDocument == "" {
outputDocument, err = makeOutputFilepath(config.RootDir, nodeID)
if err != nil {
return err
}
}
if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil {
@ -154,6 +157,8 @@ following delegation and commission default parameters:
cmd.Flags().String(tmcli.HomeFlag, app.DefaultNodeHome, "node's home directory")
cmd.Flags().String(flagClientHome, app.DefaultCLIHome, "client's home directory")
cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx")
cmd.Flags().String(client.FlagOutputDocument, "",
"write the genesis transaction JSON document to the given file instead of the default location")
cmd.Flags().AddFlagSet(cli.FsCommissionCreate)
cmd.Flags().AddFlagSet(cli.FsAmount)
cmd.Flags().AddFlagSet(cli.FsPk)

View File

@ -28,6 +28,7 @@ type printInfo struct {
Moniker string `json:"moniker"`
ChainID string `json:"chain_id"`
NodeID string `json:"node_id"`
GenTxsDir string `json:"gentxs_dir"`
AppMessage json.RawMessage `json:"app_message"`
}
@ -77,12 +78,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
return err
}
toPrint := printInfo{
ChainID: chainID,
Moniker: config.Moniker,
NodeID: nodeID,
AppMessage: appState,
}
toPrint := newPrintInfo(config.Moniker, chainID, nodeID, "", appState)
cfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config)

View File

@ -279,13 +279,7 @@ func collectGenFiles(
config.SetRoot(nodeDir)
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
initCfg := initConfig{
ChainID: chainID,
GenTxsDir: gentxsDir,
Name: moniker,
NodeID: nodeID,
ValPubKey: valPubKey,
}
initCfg := newInitConfig(chainID, gentxsDir, moniker, nodeID, valPubKey)
genDoc, err := loadGenesisDoc(cdc, config.GenesisFile())
if err != nil {

View File

@ -49,8 +49,11 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}

View File

@ -78,8 +78,11 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}
@ -123,8 +126,11 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}
@ -162,8 +168,11 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}

View File

@ -43,8 +43,11 @@ func TransferRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}

View File

@ -38,8 +38,11 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}

View File

@ -29,8 +29,6 @@ const (
FlagGenesisFormat = "genesis-format"
FlagNodeID = "node-id"
FlagIP = "ip"
FlagOutputDocument = "output-document" // inspired by wget -O
)
// common flagsets to add to various functions

View File

@ -2,81 +2,72 @@ package rest
import (
"bytes"
"io/ioutil"
"net/http"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
"github.com/cosmos/cosmos-sdk/x/stake"
"github.com/gorilla/mux"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, kb keys.Keybase) {
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/delegations",
delegationsRequestHandlerFn(cdc, kb, cliCtx),
postDelegationsHandlerFn(cdc, kb, cliCtx),
).Methods("POST")
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/unbonding_delegations",
postUnbondingDelegationsHandlerFn(cdc, kb, cliCtx),
).Methods("POST")
r.HandleFunc(
"/stake/delegators/{delegatorAddr}/redelegations",
postRedelegationsHandlerFn(cdc, kb, cliCtx),
).Methods("POST")
}
type (
msgDelegationsInput struct {
DelegatorAddr string `json:"delegator_addr"` // in bech32
ValidatorAddr string `json:"validator_addr"` // in bech32
Delegation sdk.Coin `json:"delegation"`
BaseReq utils.BaseReq `json:"base_req"`
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // in bech32
ValidatorAddr sdk.ValAddress `json:"validator_addr"` // in bech32
Delegation sdk.Coin `json:"delegation"`
}
msgBeginRedelegateInput struct {
DelegatorAddr string `json:"delegator_addr"` // in bech32
ValidatorSrcAddr string `json:"validator_src_addr"` // in bech32
ValidatorDstAddr string `json:"validator_dst_addr"` // in bech32
SharesAmount string `json:"shares"`
BaseReq utils.BaseReq `json:"base_req"`
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // in bech32
ValidatorSrcAddr sdk.ValAddress `json:"validator_src_addr"` // in bech32
ValidatorDstAddr sdk.ValAddress `json:"validator_dst_addr"` // in bech32
SharesAmount sdk.Dec `json:"shares"`
}
msgBeginUnbondingInput struct {
DelegatorAddr string `json:"delegator_addr"` // in bech32
ValidatorAddr string `json:"validator_addr"` // in bech32
SharesAmount string `json:"shares"`
}
// the request body for edit delegations
EditDelegationsReq struct {
BaseReq utils.BaseReq `json:"base_req"`
Delegations []msgDelegationsInput `json:"delegations"`
BeginUnbondings []msgBeginUnbondingInput `json:"begin_unbondings"`
BeginRedelegates []msgBeginRedelegateInput `json:"begin_redelegates"`
BaseReq utils.BaseReq `json:"base_req"`
DelegatorAddr sdk.AccAddress `json:"delegator_addr"` // in bech32
ValidatorAddr sdk.ValAddress `json:"validator_addr"` // in bech32
SharesAmount sdk.Dec `json:"shares"`
}
)
// TODO: Split this up into several smaller functions, and remove the above nolint
// TODO: use sdk.ValAddress instead of sdk.AccAddress for validators in messages
// TODO: Seriously consider how to refactor...do we need to make it multiple txs?
// If not, we can just use CompleteAndBroadcastTxREST.
func delegationsRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req EditDelegationsReq
var req msgDelegationsInput
body, err := ioutil.ReadAll(r.Body)
err := utils.ReadRESTReq(w, r, cdc, &req)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
err = cdc.UnmarshalJSON(body, &req)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w) {
if !baseReq.ValidateBasic(w, cliCtx) {
return
}
@ -86,182 +77,98 @@ func delegationsRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx conte
return
}
// build messages
messages := make([]sdk.Msg, len(req.Delegations)+
len(req.BeginRedelegates)+
len(req.BeginUnbondings))
i := 0
for _, msg := range req.Delegations {
delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if !bytes.Equal(info.GetPubKey().Address(), delAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
messages[i] = stake.MsgDelegate{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
Delegation: msg.Delegation,
}
i++
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
for _, msg := range req.BeginRedelegates {
delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if !bytes.Equal(info.GetPubKey().Address(), delAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
valSrcAddr, err := sdk.ValAddressFromBech32(msg.ValidatorSrcAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
valDstAddr, err := sdk.ValAddressFromBech32(msg.ValidatorDstAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
messages[i] = stake.MsgBeginRedelegate{
DelegatorAddr: delAddr,
ValidatorSrcAddr: valSrcAddr,
ValidatorDstAddr: valDstAddr,
SharesAmount: shares,
}
i++
}
for _, msg := range req.BeginUnbondings {
delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if !bytes.Equal(info.GetPubKey().Address(), delAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
valAddr, err := sdk.ValAddressFromBech32(msg.ValidatorAddr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
shares, err := sdk.NewDecFromStr(msg.SharesAmount)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
messages[i] = stake.MsgBeginUnbonding{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
SharesAmount: shares,
}
i++
}
simulateGas, gas, err := client.ReadGasFlag(baseReq.Gas)
msg := stake.NewMsgDelegate(req.DelegatorAddr, req.ValidatorAddr, req.Delegation)
err = msg.ValidateBasic()
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment)
if !ok {
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc)
}
}
func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req msgBeginRedelegateInput
err := utils.ReadRESTReq(w, r, cdc, &req)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
txBldr := authtxb.TxBuilder{
Codec: cdc,
Gas: gas,
GasAdjustment: adjustment,
SimulateGas: simulateGas,
ChainID: baseReq.ChainID,
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w, cliCtx) {
return
}
// sign messages
signedTxs := make([][]byte, len(messages[:]))
for i, msg := range messages {
// increment sequence for each message
txBldr = txBldr.WithAccountNumber(baseReq.AccountNumber)
txBldr = txBldr.WithSequence(baseReq.Sequence)
baseReq.Sequence++
if baseReq.Simulate || txBldr.SimulateGas {
newBldr, err := utils.EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, []sdk.Msg{msg})
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
if baseReq.Simulate {
utils.WriteSimulationResponse(w, newBldr.Gas)
return
}
txBldr = newBldr
}
if baseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, txBldr, []sdk.Msg{msg})
return
}
txBytes, err := txBldr.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg})
if err != nil {
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
signedTxs[i] = txBytes
info, err := kb.Get(baseReq.Name)
if err != nil {
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
// send
// XXX the operation might not be atomic if a tx fails
// should we have a sdk.MultiMsg type to make sending atomic?
results := make([]*ctypes.ResultBroadcastTxCommit, len(signedTxs[:]))
for i, txBytes := range signedTxs {
res, err := cliCtx.BroadcastTx(txBytes)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
results[i] = res
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
utils.PostProcessResponse(w, cdc, results, cliCtx.Indent)
msg := stake.NewMsgBeginRedelegate(req.DelegatorAddr, req.ValidatorSrcAddr, req.ValidatorDstAddr, req.SharesAmount)
err = msg.ValidateBasic()
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc)
}
}
func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req msgBeginUnbondingInput
err := utils.ReadRESTReq(w, r, cdc, &req)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly)
cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate)
baseReq := req.BaseReq.Sanitize()
if !baseReq.ValidateBasic(w, cliCtx) {
return
}
info, err := kb.Get(baseReq.Name)
if err != nil {
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
return
}
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
return
}
msg := stake.NewMsgBeginUnbonding(req.DelegatorAddr, req.ValidatorAddr, req.SharesAmount)
err = msg.ValidateBasic()
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc)
}
}