Merge branch 'dev/add_async_flag' of github.com:cosmos/cosmos-sdk into dev/add_async_flag

This commit is contained in:
ValarDragon 2018-07-05 20:15:51 -07:00
commit 2197a9598b
34 changed files with 153 additions and 117 deletions

View File

@ -5,6 +5,7 @@
*TBD*
BREAKING CHANGES
* msg.GetSignBytes() returns sorted JSON (by key)
* Update Tendermint to v0.22.0
* Default ports changed from 466xx to 266xx
* Amino JSON uses type names instead of prefix bytes
@ -41,6 +42,9 @@ BREAKING CHANGES
* [lcd] Switch key creation output to return bech32
* [x/stake] store-value for delegation, validator, ubd, and red do not hold duplicate information contained store-key
DEPRECATED
* [cli] Deprecate `--name` flag in commands that send txs, in favor of `--from`
FEATURES
* [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag
* [lcd] Queried TXs now include the tx hash to identify each tx
@ -102,6 +106,7 @@ BUG FIXES
* \#1258 - printing big.rat's can no longer overflow int64
* \#887 - limit the size of rationals that can be passed in from user input
* \#1461 - CLI tests now no longer reset your local environment data
* \#1505 - `gaiacli stake validator` no longer panics if validator doesn't exist
## 0.19.0

View File

@ -662,7 +662,7 @@ const msgType3 = "burn"
func (msg testBurnMsg) Type() string { return msgType3 }
func (msg testBurnMsg) GetSignBytes() []byte {
bz, _ := json.Marshal(msg)
return bz
return sdk.MustSortJSON(bz)
}
func (msg testBurnMsg) ValidateBasic() sdk.Error {
if msg.Addr == nil {
@ -685,7 +685,7 @@ const msgType4 = "send"
func (msg testSendMsg) Type() string { return msgType4 }
func (msg testSendMsg) GetSignBytes() []byte {
bz, _ := json.Marshal(msg)
return bz
return sdk.MustSortJSON(bz)
}
func (msg testSendMsg) ValidateBasic() sdk.Error {
if msg.Sender == nil || msg.Receiver == nil {

View File

@ -224,7 +224,7 @@ func (ctx CoreContext) ensureSignBuild(name string, msgs []sdk.Msg, cdc *wire.Co
}
// sign and build the transaction from the msg
func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec, async bool, printResponse bool) (err error) {
func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec, printResponse bool) (err error) {
txBytes, err := ctx.ensureSignBuild(name, msgs, cdc)
if err != nil {

View File

@ -27,13 +27,20 @@ func NewCoreContextFromViper() CoreContext {
chainID = def
}
}
// TODO: Remove the following deprecation code after Gaia-7000 is launched
keyName := viper.GetString(client.FlagName)
if keyName != "" {
fmt.Println("** Note --name is deprecated and will be removed next release. Please use --from instead **")
} else {
keyName = viper.GetString(client.FlagFrom)
}
return CoreContext{
ChainID: chainID,
Height: viper.GetInt64(client.FlagHeight),
Gas: viper.GetInt64(client.FlagGas),
Fee: viper.GetString(client.FlagFee),
TrustNode: viper.GetBool(client.FlagTrustNode),
FromAddressName: viper.GetString(client.FlagName),
FromAddressName: keyName,
NodeURI: nodeURI,
AccountNumber: viper.GetInt64(client.FlagAccountNumber),
Sequence: viper.GetInt64(client.FlagSequence),

View File

@ -10,6 +10,7 @@ const (
FlagHeight = "height"
FlagGas = "gas"
FlagTrustNode = "trust-node"
FlagFrom = "from"
FlagName = "name"
FlagAccountNumber = "account-number"
FlagSequence = "sequence"
@ -38,7 +39,8 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
// PostCommands adds common flags for commands to post tx
func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
for _, c := range cmds {
c.Flags().String(FlagName, "", "Name of private key with which to sign")
c.Flags().String(FlagFrom, "", "Name of private key with which to sign")
c.Flags().String(FlagName, "", "DEPRECATED - Name of private key with which to sign")
c.Flags().Int64(FlagAccountNumber, 0, "AccountNumber number to sign the tx")
c.Flags().Int64(FlagSequence, 0, "Sequence number to sign the tx")
c.Flags().String(FlagMemo, "", "Memo to send along with transaction")

View File

@ -59,7 +59,7 @@ func TestGaiaCLISend(t *testing.T) {
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags))
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass)
tests.WaitForNextHeightTM(port)
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags))
@ -68,7 +68,7 @@ func TestGaiaCLISend(t *testing.T) {
require.Equal(t, int64(40), fooAcc.GetCoins().AmountOf("steak").Int64())
// test autosequencing
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass)
tests.WaitForNextHeightTM(port)
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags))
@ -77,7 +77,7 @@ func TestGaiaCLISend(t *testing.T) {
require.Equal(t, int64(30), fooAcc.GetCoins().AmountOf("steak").Int64())
// test memo
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo --memo 'testmemo'", flags, barCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo --memo 'testmemo'", flags, barCech), pass)
tests.WaitForNextHeightTM(port)
barAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags))
@ -111,7 +111,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
barCech := sdk.MustBech32ifyAcc(barAddr)
barCeshPubKey := sdk.MustBech32ifyValPub(barPubKey)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --name=foo", flags, barCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli send %v --amount=10steak --to=%v --from=foo", flags, barCech), pass)
tests.WaitForNextHeightTM(port)
barAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", barCech, flags))
@ -121,7 +121,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
// create validator
cvStr := fmt.Sprintf("gaiacli stake create-validator %v", flags)
cvStr += fmt.Sprintf(" --name=%v", "bar")
cvStr += fmt.Sprintf(" --from=%v", "bar")
cvStr += fmt.Sprintf(" --address-validator=%v", barCech)
cvStr += fmt.Sprintf(" --pubkey=%v", barCeshPubKey)
cvStr += fmt.Sprintf(" --amount=%v", "2steak")
@ -139,7 +139,7 @@ func TestGaiaCLICreateValidator(t *testing.T) {
// unbond a single share
unbondStr := fmt.Sprintf("gaiacli stake unbond begin %v", flags)
unbondStr += fmt.Sprintf(" --name=%v", "bar")
unbondStr += fmt.Sprintf(" --from=%v", "bar")
unbondStr += fmt.Sprintf(" --address-validator=%v", barCech)
unbondStr += fmt.Sprintf(" --address-delegator=%v", barCech)
unbondStr += fmt.Sprintf(" --shares-amount=%v", "1")
@ -181,7 +181,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
fooAcc := executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags))
require.Equal(t, int64(50), fooAcc.GetCoins().AmountOf("steak").Int64())
executeWrite(t, fmt.Sprintf("gaiacli gov submitproposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --name=foo", flags, fooCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli gov submitproposal %v --proposer=%v --deposit=5steak --type=Text --title=Test --description=test --from=foo", flags, fooCech), pass)
tests.WaitForNextHeightTM(port)
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags))
@ -191,7 +191,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(1), proposal1.ProposalID)
require.Equal(t, gov.StatusToString(gov.StatusDepositPeriod), proposal1.Status)
executeWrite(t, fmt.Sprintf("gaiacli gov deposit %v --depositer=%v --deposit=10steak --proposalID=1 --name=foo", flags, fooCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli gov deposit %v --depositer=%v --deposit=10steak --proposalID=1 --from=foo", flags, fooCech), pass)
tests.WaitForNextHeightTM(port)
fooAcc = executeGetAccount(t, fmt.Sprintf("gaiacli account %v %v", fooCech, flags))
@ -200,7 +200,7 @@ func TestGaiaCLISubmitProposal(t *testing.T) {
require.Equal(t, int64(1), proposal1.ProposalID)
require.Equal(t, gov.StatusToString(gov.StatusVotingPeriod), proposal1.Status)
executeWrite(t, fmt.Sprintf("gaiacli gov vote %v --proposalID=1 --voter=%v --option=Yes --name=foo", flags, fooCech), pass)
executeWrite(t, fmt.Sprintf("gaiacli gov vote %v --proposalID=1 --voter=%v --option=Yes --from=foo", flags, fooCech), pass)
tests.WaitForNextHeightTM(port)
vote := executeGetVote(t, fmt.Sprintf("gaiacli gov query-vote --proposalID=1 --voter=%v --output=json %v", fooCech, flags))

View File

@ -220,7 +220,7 @@ gaiacli stake create-validator \
--address-validator=<account_cosmosaccaddr>
--moniker="choose a moniker" \
--chain-id=gaia-6002 \
--name=<key_name>
--from=<key_name>
```
### Edit Validator Description
@ -237,7 +237,7 @@ gaiacli stake edit-validator
--keybase-sig="6A0D65E29A4CBC8E"
--details="To infinity and beyond!"
--chain-id=gaia-6002 \
--name=<key_name>
--from=<key_name>
```
### View Validator Description
@ -272,7 +272,7 @@ gaiad start
Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmosaccaddr>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`.
```bash
gaiacli stake unrevoke <cosmosaccaddr> --chain-id=gaia-6002 --name=<name>
gaiacli stake unrevoke <cosmosaccaddr> --chain-id=gaia-6002 --from=<name>
```
**WARNING:** If you don't wait for `gaiad` to sync before running `unrevoke`, you will receive an error message telling you your validator is still jailed.
@ -321,7 +321,7 @@ gaiacli stake delegate \
--amount=10steak \
--address-delegator=<account_cosmosaccaddr> \
--address-validator=<validator_cosmosaccaddr> \
--name=<key_name> \
--from=<key_name> \
--chain-id=gaia-6002
```
@ -338,7 +338,7 @@ gaiacli stake unbond \
--address-delegator=<account_cosmosaccaddr> \
--address-validator=<validator_cosmosaccaddr> \
--shares=MAX \
--name=<key_name> \
--from=<key_name> \
--chain-id=gaia-6002
```
@ -361,7 +361,7 @@ gaiacli stake delegation \
gaiacli send \
--amount=10faucetToken \
--chain-id=gaia-6002 \
--name=<key_name> \
--from=<key_name> \
--to=<destination_cosmosaccaddr>
```

View File

@ -197,9 +197,9 @@ We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the net
::
gaiacli send --amount=1000mycoin --sequence=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU
gaiacli send --amount=1000mycoin --sequence=0 --from=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU
where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like:
where the ``--sequence`` flag is to be incremented for each transaction, the ``--from`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like:
::
@ -264,7 +264,7 @@ Now ``bob`` can create a validator with that pubkey.
::
gaiacli stake create-validator --amount=10mycoin --name=bob --address-validator=<address> --pub-key=<pubkey> --moniker=bobby
gaiacli stake create-validator --amount=10mycoin --from=bob --address-validator=<address> --pub-key=<pubkey> --moniker=bobby
with an output like:
@ -306,13 +306,13 @@ First let's have ``alice`` send some coins to ``charlie``:
::
gaiacli send --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF
gaiacli send --amount=1000mycoin --sequence=2 --from=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF
Then ``charlie`` will delegate some mycoin to ``bob``:
::
gaiacli stake delegate --amount=10mycoin --address-delegator=<charlie's address> --address-validator=<bob's address> --name=charlie
gaiacli stake delegate --amount=10mycoin --address-delegator=<charlie's address> --address-validator=<bob's address> --from=charlie
You'll see output like:
@ -396,7 +396,7 @@ your VotingPower reduce and your account balance increase.
::
gaiacli stake unbond --amount=5mycoin --name=charlie --address-delegator=<address> --address-validator=<address>
gaiacli stake unbond --amount=5mycoin --from=charlie --address-delegator=<address> --address-validator=<address>
gaiacli account 48F74F48281C89E5E4BE9092F735EA519768E8EF
See the bond decrease with ``gaiacli stake delegation`` like above.

View File

@ -63,7 +63,7 @@ Then, we try to transfer some `steak` to another account:
```
gaiacli account <FOO-ADDR>
gaiacli account <BAR-ADDR>
gaiacli send --amount=10steak --to=<BAR-ADDR> --name=foo --chain-id=test-chain
gaiacli send --amount=10steak --to=<BAR-ADDR> --from=foo --chain-id=test-chain
```
**Note:** We need to be careful with the `chain-id` and `sequence`
@ -84,7 +84,7 @@ Finally, to relinquish all your power, unbond some coins. You should see
your VotingPower reduce and your account balance increase.
```
gaiacli unbond --chain-id=<chain-id> --name=test
gaiacli unbond --chain-id=<chain-id> --from=test
```
That's it!

View File

@ -23,7 +23,7 @@ NAME: TYPE: ADDRESS: PUBKEY:
This key will only be accessible while the Ledger is plugged in and unlocked. To send some coins with this key, run the following:
```bash
$ gaiacli send --name {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000
$ gaiacli send --from {{ .Key.Name }} --to {{ .Destination.AccAddr }} --chain-id=gaia-7000
```
You will be asked to review and confirm the transaction on the Ledger. Once you do this you should see the result in the console! Now you can use your Ledger to manage your Atoms and Stake!

View File

@ -85,7 +85,7 @@ func (msg MsgSend) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bz
return sdk.MustSortJSON(bz)
}
// Implements Msg. Return the signer.

View File

@ -100,7 +100,7 @@ func (msg MsgIssue) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bz
return sdk.MustSortJSON(bz)
}
// Implements Msg. Return the signer.

View File

@ -123,12 +123,12 @@ Where `90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD` is alice's address we got from
The following command will send coins from alice, to bob:
```
basecli send --name=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D
basecli send --from=alice --amount=10000mycoin --to=29D721F054537C91F618A0FDBF770DA51EF8C48D
--sequence=0 --chain-id=test-chain-AE4XQo
```
Flag Descriptions:
- `name` is the name you gave your key
- `from` is the name you gave your key
- `mycoin` is the name of the token for this basecoin demo, initialized in the genesis.json file
- `sequence` is a tally of how many transactions have been made by this account. Since this is the first tx on this account, it is 0
- `chain-id` is the unique ID that helps tendermint identify which network to connect to. You can find it in the terminal output from the gaiad daemon in the header block , or in the genesis.json file at `~/.basecoind/config/genesis.json`
@ -142,16 +142,16 @@ basecli account 29D721F054537C91F618A0FDBF770DA51EF8C48D
Now lets send some from bob to charlie. Make sure you send less than bob has, otherwise the transaction will fail:
```
basecli send --name=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E
basecli send --from=bob --amount=5000mycoin --to=2E8E13EEB8E3F0411ACCBC9BE0384732C24FBD5E
--sequence=0 --chain-id=test-chain-AE4XQo
```
Note how we use the ``--name`` flag to select a different account to send from.
Note how we use the ``--from`` flag to select a different account to send from.
Lets now try to send from bob back to alice:
```
basecli send --name=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD
basecli send --from=bob --amount=3000mycoin --to=90B0B9BE0914ECEE0B6DB74E67B07A00056B9BBD
--sequence=1 --chain-id=test-chain-AE4XQo
```

View File

@ -58,7 +58,7 @@ func (msg MsgSetTrend) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
//_______________________________________________________________________
@ -102,5 +102,5 @@ func (msg MsgQuiz) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}

View File

@ -18,7 +18,7 @@ func (msg Msg) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bz
return sdk.MustSortJSON(bz)
}
// GetSigners implements sdk.Msg

View File

@ -76,5 +76,5 @@ func (msg MsgMine) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}

View File

@ -62,7 +62,7 @@ func TestMsgMineGetSignBytes(t *testing.T) {
addr := sdk.Address([]byte("sender"))
msg := MsgMine{addr, 1, 1, 1, []byte("abc")}
res := msg.GetSignBytes()
require.Equal(t, string(res), `{"sender":"73656E646572","difficulty":1,"count":1,"nonce":1,"proof":"YWJj"}`)
require.Equal(t, string(res), `{"count":1,"difficulty":1,"nonce":1,"proof":"YWJj","sender":"73656E646572"}`)
}
func TestMsgMineGetSigners(t *testing.T) {

View File

@ -48,7 +48,7 @@ func (msg MsgBond) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bz
return sdk.MustSortJSON(bz)
}
//_______________________________________________________________

View File

@ -27,7 +27,7 @@ func (tx kvstoreTx) GetMemo() string {
}
func (tx kvstoreTx) GetSignBytes() []byte {
return tx.bytes
return sdk.MustSortJSON(tx.bytes)
}
// Should the app be calling this? Or only handlers?

View File

@ -141,24 +141,6 @@ func InsertKeyJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawM
return json.RawMessage(bz), err
}
// SortedJSON takes any JSON and returns it sorted by keys. Also, all white-spaces
// are removed.
// This method can be used to canonicalize JSON to be returned by GetSignBytes,
// e.g. for the ledger integration.
// If the passed JSON isn't valid it will return an error.
func SortJSON(toSortJSON []byte) ([]byte, error) {
var c interface{}
err := json.Unmarshal(toSortJSON, &c)
if err != nil {
return nil, err
}
js, err := json.Marshal(c)
if err != nil {
return nil, err
}
return js, nil
}
// https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go
// TODO there must be a better way to get external IP
func externalIP() (string, error) {

View File

@ -38,34 +38,3 @@ func TestInsertKeyJSON(t *testing.T) {
require.Equal(t, bar, resBar, "appended: %v", appended)
}
func TestSortJSON(t *testing.T) {
cases := []struct {
unsortedJSON string
want string
wantErr bool
}{
// simple case
{unsortedJSON: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`,
want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false},
// failing case (invalid JSON):
{unsortedJSON: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`,
want: "", wantErr: true},
// genesis.json
{unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`,
want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`,
wantErr: false},
// from the TXSpec:
{unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`,
want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`,
wantErr: false},
}
for _, tc := range cases {
got, err := SortJSON([]byte(tc.unsortedJSON))
if tc.wantErr != (err != nil) {
t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err)
}
require.Equal(t, string(got), tc.want)
}
}

View File

@ -36,7 +36,7 @@ echo; echo "Empty account:" $TO
./build/basecli account $TO
# send some money
TX=`echo $PASS | ./build/basecli send --to=$TO --amount=1000mycoin --name=demo --seq=0`
TX=`echo $PASS | ./build/basecli send --to=$TO --amount=1000mycoin --from=demo --seq=0`
echo; echo "SendTx"; echo $TX
HASH=`echo $TX | cut -d' ' -f6`
echo "tx hash:" $HASH

View File

@ -60,7 +60,7 @@ func (msg *TestMsg) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bz
return MustSortJSON(bz)
}
func (msg *TestMsg) ValidateBasic() Error { return nil }
func (msg *TestMsg) GetSigners() []Address {

31
types/utils.go Normal file
View File

@ -0,0 +1,31 @@
package types
import "encoding/json"
// SortedJSON takes any JSON and returns it sorted by keys. Also, all white-spaces
// are removed.
// This method can be used to canonicalize JSON to be returned by GetSignBytes,
// e.g. for the ledger integration.
// If the passed JSON isn't valid it will return an error.
func SortJSON(toSortJSON []byte) ([]byte, error) {
var c interface{}
err := json.Unmarshal(toSortJSON, &c)
if err != nil {
return nil, err
}
js, err := json.Marshal(c)
if err != nil {
return nil, err
}
return js, nil
}
// MustSortJSON is like SortJSON but panic if an error occurs, e.g., if
// the passed JSON isn't valid.
func MustSortJSON(toSortJSON []byte) []byte {
js, err := SortJSON(toSortJSON)
if err != nil {
panic(err)
}
return js
}

39
types/utils_test.go Normal file
View File

@ -0,0 +1,39 @@
package types
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestSortJSON(t *testing.T) {
cases := []struct {
unsortedJSON string
want string
wantErr bool
}{
// simple case
{unsortedJSON: `{"cosmos":"foo", "atom":"bar", "tendermint":"foobar"}`,
want: `{"atom":"bar","cosmos":"foo","tendermint":"foobar"}`, wantErr: false},
// failing case (invalid JSON):
{unsortedJSON: `"cosmos":"foo",,,, "atom":"bar", "tendermint":"foobar"}`,
want: "",
wantErr: true},
// genesis.json
{unsortedJSON: `{"consensus_params":{"block_size_params":{"max_bytes":22020096,"max_txs":100000,"max_gas":-1},"tx_size_params":{"max_bytes":10240,"max_gas":-1},"block_gossip_params":{"block_part_size_bytes":65536},"evidence_params":{"max_age":100000}},"validators":[{"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="},"power":100,"name":""}],"app_hash":"","genesis_time":"2018-05-11T15:52:25.424795506Z","chain_id":"test-chain-Q6VeoW","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"denom":"Token","amount":1000},{"denom":"steak","amount":50}]}],"stake":{"pool":{"total_supply":50,"bonded_shares":"0","unbonded_shares":"0","bonded_pool":0,"unbonded_pool":0,"inflation_last_time":0,"inflation":"7/100"},"params":{"inflation_rate_change":"13/100","inflation_max":"1/5","inflation_min":"7/100","goal_bonded":"67/100","max_validators":100,"bond_denom":"steak"},"candidates":null,"bonds":null}}}`,
want: `{"app_hash":"","app_state":{"accounts":[{"address":"718C9C23F98C9642569742ADDD9F9AB9743FBD5D","coins":[{"amount":1000,"denom":"Token"},{"amount":50,"denom":"steak"}]}],"stake":{"bonds":null,"candidates":null,"params":{"bond_denom":"steak","goal_bonded":"67/100","inflation_max":"1/5","inflation_min":"7/100","inflation_rate_change":"13/100","max_validators":100},"pool":{"bonded_pool":0,"bonded_shares":"0","inflation":"7/100","inflation_last_time":0,"total_supply":50,"unbonded_pool":0,"unbonded_shares":"0"}}},"chain_id":"test-chain-Q6VeoW","consensus_params":{"block_gossip_params":{"block_part_size_bytes":65536},"block_size_params":{"max_bytes":22020096,"max_gas":-1,"max_txs":100000},"evidence_params":{"max_age":100000},"tx_size_params":{"max_bytes":10240,"max_gas":-1}},"genesis_time":"2018-05-11T15:52:25.424795506Z","validators":[{"name":"","power":100,"pub_key":{"type":"AC26791624DE60","value":"c7UMMAbjFuc5GhGPy0E5q5tefy12p9Tq0imXqdrKXwo="}}]}`,
wantErr: false},
// from the TXSpec:
{unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"alt_bytes":null}`,
want: `{"alt_bytes":null,"chain_id":"test-chain-1","fee_bytes":{"amount":[{"amount":5,"denom":"photon"}],"gas":10000},"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":10,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":10,"denom":"atom"}]}]},"sequence":1}`,
wantErr: false},
}
for _, tc := range cases {
got, err := SortJSON([]byte(tc.unsortedJSON))
if tc.wantErr != (err != nil) {
t.Fatalf("got %t, want: %t, err=%s", err != nil, tc.wantErr, err)
}
require.Equal(t, string(got), tc.want)
}
}

View File

@ -141,7 +141,7 @@ func StdSignBytes(chainID string, accnum int64, sequence int64, fee StdFee, msgs
if err != nil {
panic(err)
}
return bz
return sdk.MustSortJSON(bz)
}
// StdSignMsg is a convenience structure for passing along

View File

@ -72,7 +72,7 @@ func (msg MsgSend) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// Implements Msg.
@ -133,7 +133,7 @@ func (msg MsgIssue) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// Implements Msg.
@ -162,7 +162,7 @@ func (in Input) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bin
return sdk.MustSortJSON(bin)
}
// ValidateBasic - validate transaction input
@ -209,7 +209,7 @@ func (out Output) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return bin
return sdk.MustSortJSON(bin)
}
// ValidateBasic - validate transaction output

View File

@ -187,7 +187,7 @@ func TestMsgSendGetSignBytes(t *testing.T) {
}
res := msg.GetSignBytes()
expected := `{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"denom":"atom","amount":"10"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"denom":"atom","amount":"10"}]}]}`
expected := `{"inputs":[{"address":"cosmosaccaddr1d9h8qat5e4ehc5","coins":[{"amount":"10","denom":"atom"}]}],"outputs":[{"address":"cosmosaccaddr1da6hgur4wse3jx32","coins":[{"amount":"10","denom":"atom"}]}]}`
require.Equal(t, expected, string(res))
}
@ -257,7 +257,7 @@ func TestMsgIssueGetSignBytes(t *testing.T) {
}
res := msg.GetSignBytes()
expected := `{"banker":"cosmosaccaddr1d9h8qat5e4ehc5","outputs":[{"address":"cosmosaccaddr1d3hkzm3dveex7mfdvfsku6cwsauqd","coins":[{"denom":"atom","amount":"10"}]}]}`
expected := `{"banker":"cosmosaccaddr1d9h8qat5e4ehc5","outputs":[{"address":"cosmosaccaddr1d3hkzm3dveex7mfdvfsku6cwsauqd","coins":[{"amount":"10","denom":"atom"}]}]}`
require.Equal(t, expected, string(res))
}

View File

@ -82,7 +82,7 @@ func (msg MsgSubmitProposal) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// Implements Msg.
@ -149,7 +149,7 @@ func (msg MsgDeposit) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// Implements Msg.
@ -213,7 +213,7 @@ func (msg MsgVote) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// Implements Msg.

View File

@ -109,7 +109,7 @@ key2 DC26002735D3AA9573707CFA6D77C12349E49868
## Transfer coins (addr1:chain1 -> addr2:chain2)
```console
> basecli transfer --name key1 --to $ADDR2 --amount 10mycoin --chain $ID2 --chain-id $ID1 --node $NODE1
> basecli transfer --from key1 --to $ADDR2 --amount 10mycoin --chain $ID2 --chain-id $ID1 --node $NODE1
Password to sign with 'key1':
Committed at block 1022. Hash: E16019DCC4AA08CA70AFCFBC96028ABCC51B6AD0
> basecli account $ADDR1 --node $NODE1
@ -133,7 +133,7 @@ Committed at block 1022. Hash: E16019DCC4AA08CA70AFCFBC96028ABCC51B6AD0
## Relay IBC packets
```console
> basecli relay --name key2 --from-chain-id $ID1 --from-chain-node $NODE1 --to-chain-id $ID2 --to-chain-node $NODE2 --chain-id $ID2
> basecli relay --from key2 --from-chain-id $ID1 --from-chain-node $NODE1 --to-chain-id $ID2 --to-chain-node $NODE2 --chain-id $ID2
Password to sign with 'key2':
I[04-03|16:18:59.984] Detected IBC packet number=0
I[04-03|16:19:00.869] Relayed IBC packet number=0

View File

@ -59,7 +59,7 @@ func (p IBCPacket) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// validator the ibc packey
@ -131,5 +131,5 @@ func (msg IBCReceiveMsg) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}

View File

@ -38,7 +38,7 @@ func (msg MsgUnrevoke) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check

View File

@ -31,8 +31,9 @@ func GetCmdQueryValidator(storeName string, cdc *wire.Codec) *cobra.Command {
res, err := ctx.QueryStore(key, storeName)
if err != nil {
return err
} else if len(res) == 0 {
return fmt.Errorf("No validator found with address %s", args[0])
}
validator := types.MustUnmarshalValidator(cdc, addr, res)
switch viper.Get(cli.OutputFlag) {

View File

@ -63,7 +63,7 @@ func (msg MsgCreateValidator) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -114,7 +114,7 @@ func (msg MsgEditValidator) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -166,7 +166,7 @@ func (msg MsgDelegate) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -226,7 +226,7 @@ func (msg MsgBeginRedelegate) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -286,7 +286,7 @@ func (msg MsgCompleteRedelegate) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -338,7 +338,7 @@ func (msg MsgBeginUnbonding) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check
@ -387,7 +387,7 @@ func (msg MsgCompleteUnbonding) GetSignBytes() []byte {
if err != nil {
panic(err)
}
return b
return sdk.MustSortJSON(b)
}
// quick validity check