Merge PR #1266: Multiple messages

* Started work on multiple msgs, types and x/auth tests pass
* Fix issues in x, examples, and baseapp
* Added baseapp tests for multiple msgs
* Documentation fixes
* Fix baseapp tests with sdk.Int
* Modify test
* Transaction handling is now atomic
* Fix test comment
* Minor doc fixes and code cleanup
* Added baseapp result changes
* Use address in validator update accumulation
* Started work on multiple msgs, types and x/auth tests pass
* Fix issues in x, examples, and baseapp
* Added baseapp tests for multiple msgs
* Documentation fixes
* Fix baseapp tests with sdk.Int
* Modify test
* Transaction handling is now atomic
* Fix test comment
* Minor doc fixes and code cleanup
* Added baseapp result changes
* Use address in validator update accumulation
* Added ante tests for multisigner
* Remove validatorUpdates from tx result
* Better error logs
* Put Memo in StdSignBytes and formatting
* Updated changelog
This commit is contained in:
Aditya 2018-06-21 15:05:25 -07:00 committed by Christopher Goes
parent 3fa68249eb
commit f049a56376
35 changed files with 657 additions and 232 deletions

View File

@ -7,6 +7,8 @@
BREAKING CHANGES
* Change default ports from 466xx to 266xx
* AltBytes renamed to Memo, now a string, max 100 characters, costs a bit of gas
* Transactions now take a list of Messages
* Signers of a transaction now only sign over their account and sequence number
FEATURES
* [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag

View File

@ -64,11 +64,8 @@ type BaseApp struct {
// checkState is set on initialization and reset on Commit.
// deliverState is set in InitChain and BeginBlock and cleared on Commit.
// See methods setCheckState and setDeliverState.
// .valUpdates accumulate in DeliverTx and are reset in BeginBlock.
// QUESTION: should we put valUpdates in the deliverState.ctx?
checkState *state // for CheckTx
deliverState *state // for DeliverTx
valUpdates []abci.Validator // cached validator changes from DeliverTx
signedValidators []abci.SigningValidator // absent validators from begin block
}
@ -387,7 +384,6 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
if app.deliverState == nil {
app.setDeliverState(req.Header)
}
app.valUpdates = nil
if app.beginBlocker != nil {
res = app.beginBlocker(app.deliverState.ctx, req)
}
@ -432,13 +428,8 @@ func (app *BaseApp) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
result = app.runTx(runTxModeDeliver, txBytes, tx)
}
// After-handler hooks.
if result.IsOK() {
app.valUpdates = append(app.valUpdates, result.ValidatorUpdates...)
} else {
// Even though the Result.Code is not OK, there are still effects,
// namely fee deductions and sequence incrementing.
}
// Even though the Result.Code is not OK, there are still effects,
// namely fee deductions and sequence incrementing.
// Tell the blockchain engine (i.e. Tendermint).
return abci.ResponseDeliverTx{
@ -484,16 +475,18 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
}()
// Get the Msg.
var msg = tx.GetMsg()
if msg == nil {
return sdk.ErrInternal("Tx.GetMsg() returned nil").Result()
var msgs = tx.GetMsgs()
if msgs == nil || len(msgs) == 0 {
return sdk.ErrInternal("Tx.GetMsgs() must return at least one message in list").Result()
}
// Validate the Msg.
err := msg.ValidateBasic()
if err != nil {
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
return err.Result()
for _, msg := range msgs {
// Validate the Msg
err := msg.ValidateBasic()
if err != nil {
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
return err.Result()
}
}
// Get the context
@ -521,13 +514,6 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
}
}
// Match route.
msgType := msg.Type()
handler := app.router.Route(msgType)
if handler == nil {
return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgType).Result()
}
// Get the correct cache
var msCache sdk.CacheMultiStore
if mode == runTxModeCheck || mode == runTxModeSimulate {
@ -540,25 +526,59 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
ctx = ctx.WithMultiStore(msCache)
}
result = handler(ctx, msg)
finalResult := sdk.Result{}
var logs []string
for i, msg := range msgs {
// Match route.
msgType := msg.Type()
handler := app.router.Route(msgType)
if handler == nil {
return sdk.ErrUnknownRequest("Unrecognized Msg type: " + msgType).Result()
}
// Set gas utilized
result.GasUsed = ctx.GasMeter().GasConsumed()
result = handler(ctx, msg)
// Set gas utilized
finalResult.GasUsed += ctx.GasMeter().GasConsumed()
finalResult.GasWanted += result.GasWanted
// Append Data and Tags
finalResult.Data = append(finalResult.Data, result.Data...)
finalResult.Tags = append(finalResult.Tags, result.Tags...)
// Construct usable logs in multi-message transactions. Messages are 1-indexed in logs.
logs = append(logs, fmt.Sprintf("Msg %d: %s", i+1, finalResult.Log))
// Stop execution and return on first failed message.
if !result.IsOK() {
if len(msgs) == 1 {
return result
}
result.GasUsed = finalResult.GasUsed
if i == 0 {
result.Log = fmt.Sprintf("Msg 1 failed: %s", result.Log)
} else {
result.Log = fmt.Sprintf("Msg 1-%d Passed. Msg %d failed: %s", i, i+1, result.Log)
}
return result
}
}
// If not a simulated run and result was successful, write to app.checkState.ms or app.deliverState.ms
// Only update state if all messages pass.
if mode != runTxModeSimulate && result.IsOK() {
msCache.Write()
}
return result
finalResult.Log = strings.Join(logs, "\n")
return finalResult
}
// Implements ABCI
func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
if app.endBlocker != nil {
res = app.endBlocker(app.deliverState.ctx, req)
} else {
res.ValidatorUpdates = app.valUpdates
}
return
}

View File

@ -3,6 +3,7 @@ package baseapp
import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/x/bank"
"os"
"testing"
@ -29,7 +30,7 @@ func newBaseApp(name string) *BaseApp {
logger := defaultLogger()
db := dbm.NewMemDB()
codec := wire.NewCodec()
wire.RegisterCrypto(codec)
auth.RegisterBaseAccount(codec)
return NewBaseApp(name, codec, logger, db)
}
@ -262,8 +263,8 @@ type testTx struct {
const msgType2 = "testTx"
func (tx testTx) Type() string { return msgType2 }
func (tx testTx) GetMsg() sdk.Msg { return tx }
func (tx testTx) GetMemo() string { return "" }
func (tx testTx) GetMsgs() []sdk.Msg { return []sdk.Msg{tx} }
func (tx testTx) GetSignBytes() []byte { return nil }
func (tx testTx) GetSigners() []sdk.Address { return nil }
func (tx testTx) GetSignatures() []auth.StdSignature { return nil }
@ -547,8 +548,8 @@ type testUpdatePowerTx struct {
const msgType = "testUpdatePowerTx"
func (tx testUpdatePowerTx) Type() string { return msgType }
func (tx testUpdatePowerTx) GetMsg() sdk.Msg { return tx }
func (tx testUpdatePowerTx) GetMemo() string { return "" }
func (tx testUpdatePowerTx) GetMsgs() []sdk.Msg { return []sdk.Msg{tx} }
func (tx testUpdatePowerTx) GetSignBytes() []byte { return nil }
func (tx testUpdatePowerTx) ValidateBasic() sdk.Error { return nil }
func (tx testUpdatePowerTx) GetSigners() []sdk.Address { return nil }
@ -640,6 +641,318 @@ func TestValidatorChange(t *testing.T) {
//----------------------------------------
// Use burn and send msg types to test multiple msgs in one tx
type testBurnMsg struct {
Addr sdk.Address
Amount sdk.Coins
}
const msgType3 = "burn"
func (msg testBurnMsg) Type() string { return msgType3 }
func (msg testBurnMsg) GetSignBytes() []byte {
bz, _ := json.Marshal(msg)
return bz
}
func (msg testBurnMsg) ValidateBasic() sdk.Error {
if msg.Addr == nil {
return sdk.ErrInvalidAddress("Cannot use nil as Address")
}
return nil
}
func (msg testBurnMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Addr}
}
type testSendMsg struct {
Sender sdk.Address
Receiver sdk.Address
Amount sdk.Coins
}
const msgType4 = "send"
func (msg testSendMsg) Type() string { return msgType4 }
func (msg testSendMsg) GetSignBytes() []byte {
bz, _ := json.Marshal(msg)
return bz
}
func (msg testSendMsg) ValidateBasic() sdk.Error {
if msg.Sender == nil || msg.Receiver == nil {
return sdk.ErrInvalidAddress("Cannot use nil as Address")
}
return nil
}
func (msg testSendMsg) GetSigners() []sdk.Address {
return []sdk.Address{msg.Sender}
}
// Simple Handlers for burn and send
func newHandleBurn(keeper bank.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
burnMsg := msg.(testBurnMsg)
_, _, err := keeper.SubtractCoins(ctx, burnMsg.Addr, burnMsg.Amount)
if err != nil {
return err.Result()
}
return sdk.Result{}
}
}
func newHandleSpend(keeper bank.Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
spendMsg := msg.(testSendMsg)
_, _, err := keeper.SubtractCoins(ctx, spendMsg.Sender, spendMsg.Amount)
if err != nil {
return err.Result()
}
_, _, err = keeper.AddCoins(ctx, spendMsg.Receiver, spendMsg.Amount)
if err != nil {
return err.Result()
}
return sdk.Result{}
}
}
// generate a signed transaction
func GenTx(chainID string, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKey) auth.StdTx {
// make the transaction free
fee := auth.StdFee{
sdk.Coins{{"foocoin", sdk.NewInt(0)}},
100000,
}
sigs := make([]auth.StdSignature, len(priv))
for i, p := range priv {
sigs[i] = auth.StdSignature{
PubKey: p.PubKey(),
Signature: p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, "")),
AccountNumber: accnums[i],
Sequence: seq[i],
}
}
return auth.NewStdTx(msgs, fee, sigs, "")
}
// spin up simple app for testing
type testApp struct {
*BaseApp
accountMapper auth.AccountMapper
accountKeeper bank.Keeper
}
func newTestApp(name string) testApp {
return testApp{
BaseApp: newBaseApp(name),
}
}
func MakeCodec() *wire.Codec {
cdc := wire.NewCodec()
cdc.RegisterInterface((*sdk.Msg)(nil), nil)
crypto.RegisterAmino(cdc)
cdc.RegisterInterface((*auth.Account)(nil), nil)
cdc.RegisterConcrete(&auth.BaseAccount{}, "cosmos-sdk/BaseAccount", nil)
return cdc
}
// tests multiple msgs of same type from same address in single tx
func TestMultipleBurn(t *testing.T) {
// Create app.
app := newTestApp(t.Name())
capKey := sdk.NewKVStoreKey("key")
app.MountStoresIAVL(capKey)
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx auth.StdTx
fromJSON(txBytes, &tx)
return tx, nil
})
err := app.LoadLatestVersion(capKey)
if err != nil {
panic(err)
}
app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{})
app.accountKeeper = bank.NewKeeper(app.accountMapper)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{}))
app.Router().
AddRoute("burn", newHandleBurn(app.accountKeeper)).
AddRoute("send", newHandleSpend(app.accountKeeper))
app.InitChain(abci.RequestInitChain{})
app.BeginBlock(abci.RequestBeginBlock{})
// Set chain-id
app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name())
priv := makePrivKey("my secret")
addr := priv.PubKey().Address()
app.accountKeeper.AddCoins(app.deliverState.ctx, addr, sdk.Coins{{"foocoin", sdk.NewInt(100)}})
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr), "Balance did not update")
msg := testBurnMsg{addr, sdk.Coins{{"foocoin", sdk.NewInt(50)}}}
tx := GenTx(t.Name(), []sdk.Msg{msg, msg}, []int64{0}, []int64{0}, priv)
res := app.Deliver(tx)
assert.Equal(t, true, res.IsOK(), res.Log)
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr), "Double burn did not work")
}
// tests multiples msgs of same type from different addresses in single tx
func TestBurnMultipleOwners(t *testing.T) {
// Create app.
app := newTestApp(t.Name())
capKey := sdk.NewKVStoreKey("key")
app.MountStoresIAVL(capKey)
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx auth.StdTx
fromJSON(txBytes, &tx)
return tx, nil
})
err := app.LoadLatestVersion(capKey)
if err != nil {
panic(err)
}
app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{})
app.accountKeeper = bank.NewKeeper(app.accountMapper)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{}))
app.Router().
AddRoute("burn", newHandleBurn(app.accountKeeper)).
AddRoute("send", newHandleSpend(app.accountKeeper))
app.InitChain(abci.RequestInitChain{})
app.BeginBlock(abci.RequestBeginBlock{})
// Set chain-id
app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name())
priv1 := makePrivKey("my secret 1")
addr1 := priv1.PubKey().Address()
priv2 := makePrivKey("my secret 2")
addr2 := priv2.PubKey().Address()
// fund accounts
app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}})
app.accountKeeper.AddCoins(app.deliverState.ctx, addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}})
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not update")
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not update")
msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}}}
msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(100)}}}
// test wrong signers: Address 1 signs both messages
tx := GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 0}, []int64{0, 0}, priv1, priv1)
res := app.Deliver(tx)
assert.Equal(t, sdk.ABCICodeType(0x10003), res.Code, "Wrong signatures passed")
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 changed after invalid sig")
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 changed after invalid sig")
// test valid tx
tx = GenTx(t.Name(), []sdk.Msg{msg1, msg2}, []int64{0, 1}, []int64{1, 0}, priv1, priv2)
res = app.Deliver(tx)
assert.Equal(t, true, res.IsOK(), res.Log)
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not change after valid tx")
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not change after valid tx")
}
// tests different msg types in single tx with different addresses
func TestSendBurn(t *testing.T) {
// Create app.
app := newTestApp(t.Name())
capKey := sdk.NewKVStoreKey("key")
app.MountStoresIAVL(capKey)
app.SetTxDecoder(func(txBytes []byte) (sdk.Tx, sdk.Error) {
var tx auth.StdTx
fromJSON(txBytes, &tx)
return tx, nil
})
err := app.LoadLatestVersion(capKey)
if err != nil {
panic(err)
}
app.accountMapper = auth.NewAccountMapper(app.cdc, capKey, &auth.BaseAccount{})
app.accountKeeper = bank.NewKeeper(app.accountMapper)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.FeeCollectionKeeper{}))
app.Router().
AddRoute("burn", newHandleBurn(app.accountKeeper)).
AddRoute("send", newHandleSpend(app.accountKeeper))
app.InitChain(abci.RequestInitChain{})
app.BeginBlock(abci.RequestBeginBlock{})
// Set chain-id
app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name())
priv1 := makePrivKey("my secret 1")
addr1 := priv1.PubKey().Address()
priv2 := makePrivKey("my secret 2")
addr2 := priv2.PubKey().Address()
// fund accounts
app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(100)}})
acc := app.accountMapper.NewAccountWithAddress(app.deliverState.ctx, addr2)
app.accountMapper.SetAccount(app.deliverState.ctx, acc)
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(100)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not update")
sendMsg := testSendMsg{addr1, addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}}
msg1 := testBurnMsg{addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}}}
msg2 := testBurnMsg{addr2, sdk.Coins{{"foocoin", sdk.NewInt(50)}}}
// send then burn
tx := GenTx(t.Name(), []sdk.Msg{sendMsg, msg2, msg1}, []int64{0, 1}, []int64{0, 0}, priv1, priv2)
res := app.Deliver(tx)
assert.Equal(t, true, res.IsOK(), res.Log)
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Balance1 did not change after valid tx")
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 did not change after valid tx")
// Check that state is only updated if all msgs in tx pass.
app.accountKeeper.AddCoins(app.deliverState.ctx, addr1, sdk.Coins{{"foocoin", sdk.NewInt(50)}})
// burn then send
tx = GenTx(t.Name(), []sdk.Msg{msg1, sendMsg}, []int64{0}, []int64{1}, priv1)
res = app.Deliver(tx)
// Double check that state is correct after Commit.
app.EndBlock(abci.RequestEndBlock{})
app.Commit()
app.BeginBlock(abci.RequestBeginBlock{})
app.deliverState.ctx = app.deliverState.ctx.WithChainID(t.Name())
assert.Equal(t, sdk.ABCICodeType(0x1000a), res.Code, "Allowed tx to pass with insufficient funds")
assert.Equal(t, sdk.Coins{{"foocoin", sdk.NewInt(50)}}, app.accountKeeper.GetCoins(app.deliverState.ctx, addr1), "Allowed valid msg to pass in invalid tx")
assert.Equal(t, sdk.Coins(nil), app.accountKeeper.GetCoins(app.deliverState.ctx, addr2), "Balance2 changed after invalid tx")
}
//----------------------------------------
func randPower() int64 {
return cmn.RandInt64()
}

View File

@ -114,7 +114,7 @@ func (ctx CoreContext) GetFromAddress() (from sdk.Address, err error) {
}
// sign and build the transaction from the msg
func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *wire.Codec) ([]byte, error) {
func (ctx CoreContext) SignAndBuild(name, passphrase string, msgs []sdk.Msg, cdc *wire.Codec) ([]byte, error) {
// build the Sign Messsage from the Standard Message
chainID := ctx.ChainID
@ -126,12 +126,12 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w
memo := ctx.Memo
signMsg := auth.StdSignMsg{
ChainID: chainID,
AccountNumbers: []int64{accnum},
Sequences: []int64{sequence},
Msg: msg,
Memo: memo,
Fee: auth.NewStdFee(ctx.Gas, sdk.Coin{}), // TODO run simulate to estimate gas?
ChainID: chainID,
AccountNumber: int64(accnum),
Sequence: int64(sequence),
Msgs: msgs,
Memo: memo,
Fee: auth.NewStdFee(ctx.Gas, sdk.Coin{}), // TODO run simulate to estimate gas?
}
keybase, err := keys.GetKeyBase()
@ -154,13 +154,13 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w
}}
// marshal bytes
tx := auth.NewStdTx(signMsg.Msg, signMsg.Fee, sigs, memo)
tx := auth.NewStdTx(signMsg.Msgs, signMsg.Fee, sigs, memo)
return cdc.MarshalBinary(tx)
}
// sign and build the transaction from the msg
func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) {
func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) {
ctx, err = EnsureAccountNumber(ctx)
if err != nil {
@ -177,7 +177,7 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msg sdk.Msg, cdc *w
return nil, err
}
txBytes, err := ctx.SignAndBuild(name, passphrase, msg, cdc)
txBytes, err := ctx.SignAndBuild(name, passphrase, msgs, cdc)
if err != nil {
return nil, err
}

View File

@ -101,6 +101,7 @@ func GaiaAppGenTx(cdc *wire.Codec, pk crypto.PubKey, genTxConfig config.GenTx) (
}
cliPrint = json.RawMessage(bz)
appGenTx, _, validator, err = GaiaAppGenTxNF(cdc, pk, addr, genTxConfig.Name, genTxConfig.Overwrite)
return
}

View File

@ -15,7 +15,7 @@ The design of the Cosmos SDK is based on the principles of "capabilities systems
## Tx & Msg
The SDK distinguishes between transactions (Tx) and messages
(Msg). A Tx is a Msg wrapped with authentication and fee data.
(Msg). A Tx is a list of Msgs wrapped with authentication and fee data.
### Messages
@ -92,13 +92,12 @@ func (msg MsgIssue) GetSigners() []sdk.Address {
### Transactions
A transaction is a message with additional information for authentication:
A transaction is a list of messages with additional information for authentication:
```go
type Tx interface {
GetMsg() Msg
GetMsgs() Msg
}
```

View File

@ -90,17 +90,17 @@ func TestMsgQuiz(t *testing.T) {
assert.Equal(t, acc1, res1)
// Set the trend, submit a really cool quiz and check for reward
mock.SignCheckDeliver(t, mapp.BaseApp, setTrendMsg1, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg1, []int64{0}, []int64{1}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 69)})
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg2, []int64{0}, []int64{2}, false, priv1) // result without reward
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 69)})
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg1, []int64{0}, []int64{3}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 138)})
mock.SignCheckDeliver(t, mapp.BaseApp, setTrendMsg2, []int64{0}, []int64{4}, true, priv1) // reset the trend
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg1, []int64{0}, []int64{5}, false, priv1) // the same answer will nolonger do!
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 138)})
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg2, []int64{0}, []int64{6}, true, priv1) // earlier answer now relavent again
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("badvibesonly", 69), sdk.NewCoin("icecold", 138)})
mock.SignCheckDeliver(t, mapp.BaseApp, setTrendMsg3, []int64{0}, []int64{7}, false, priv1) // expect to fail to set the trend to something which is not cool
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg1}, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{1}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg2}, []int64{0}, []int64{2}, false, priv1) // result without reward
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{3}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg2}, []int64{0}, []int64{4}, true, priv1) // reset the trend
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{5}, false, priv1) // the same answer will nolonger do!
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg2}, []int64{0}, []int64{6}, true, priv1) // earlier answer now relavent again
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"badvibesonly", sdk.NewInt(69)}, {"icecold", sdk.NewInt(138)}})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{setTrendMsg3}, []int64{0}, []int64{7}, false, priv1) // expect to fail to set the trend to something which is not cool
}

View File

@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
@ -36,7 +37,7 @@ func QuizTxCmd(cdc *wire.Codec) *cobra.Command {
name := viper.GetString(client.FlagName)
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}
@ -69,7 +70,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command {
msg := cool.NewMsgSetTrend(from, args[0])
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -72,13 +72,13 @@ func TestMsgMine(t *testing.T) {
// Mine and check for reward
mineMsg1 := GenerateMsgMine(addr1, 1, 2)
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg1, []int64{0}, []int64{0}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 1)})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg1}, []int64{0}, []int64{0}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(1)}})
// Mine again and check for reward
mineMsg2 := GenerateMsgMine(addr1, 2, 3)
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg2, []int64{0}, []int64{1}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 2)})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
// Mine again - should be invalid
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg2, []int64{0}, []int64{1}, false, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 2)})
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, false, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
}

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
)
@ -48,7 +49,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command {
name := ctx.FromAddressName
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(name, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(name, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -87,7 +87,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command {
func sendMsg(cdc *wire.Codec, msg sdk.Msg) error {
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -1,9 +1,6 @@
package simplestake
import (
abci "github.com/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -22,35 +19,15 @@ func NewHandler(k Keeper) sdk.Handler {
}
func handleMsgBond(ctx sdk.Context, k Keeper, msg MsgBond) sdk.Result {
power, err := k.Bond(ctx, msg.Address, msg.PubKey, msg.Stake)
if err != nil {
return err.Result()
}
valSet := abci.Validator{
PubKey: tmtypes.TM2PB.PubKey(msg.PubKey),
Power: power,
}
// Removed ValidatorSet from result because it does not get used.
// TODO: Implement correct bond/unbond handling
return sdk.Result{
Code: sdk.ABCICodeOK,
ValidatorUpdates: abci.Validators{valSet},
Code: sdk.ABCICodeOK,
}
}
func handleMsgUnbond(ctx sdk.Context, k Keeper, msg MsgUnbond) sdk.Result {
pubKey, _, err := k.Unbond(ctx, msg.Address)
if err != nil {
return err.Result()
}
valSet := abci.Validator{
PubKey: tmtypes.TM2PB.PubKey(pubKey),
Power: int64(0),
}
return sdk.Result{
Code: sdk.ABCICodeOK,
ValidatorUpdates: abci.Validators{valSet},
Code: sdk.ABCICodeOK,
}
}

BIN
examples/kvstore/kvstore Executable file

Binary file not shown.

View File

@ -18,8 +18,8 @@ func (tx kvstoreTx) Type() string {
return "kvstore"
}
func (tx kvstoreTx) GetMsg() sdk.Msg {
return tx
func (tx kvstoreTx) GetMsgs() []sdk.Msg {
return []sdk.Msg{tx}
}
func (tx kvstoreTx) GetMemo() string {

View File

@ -31,8 +31,8 @@ func (tx kvstoreTx) Type() string {
return "kvstore"
}
func (tx kvstoreTx) GetMsg() sdk.Msg {
return tx
func (tx kvstoreTx) GetMsgs() []sdk.Msg {
return []sdk.Msg{tx}
}
func (tx kvstoreTx) GetMemo() string {

View File

@ -1,9 +1,5 @@
package types
import (
abci "github.com/tendermint/abci/types"
)
// Result is the union of ResponseDeliverTx and ResponseCheckTx.
type Result struct {
@ -26,9 +22,6 @@ type Result struct {
FeeAmount int64
FeeDenom string
// Changes to the validator set.
ValidatorUpdates []abci.Validator
// Tags are used for transaction indexing and pubsub.
Tags Tags
}

View File

@ -30,7 +30,7 @@ type Msg interface {
type Tx interface {
// Gets the Msg.
GetMsg() Msg
GetMsgs() []Msg
// Gets the memo.
GetMemo() string

View File

@ -52,10 +52,10 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
// charge gas for the memo
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(memo)), "memo")
msg := tx.GetMsg()
msgs := tx.GetMsgs()
// Assert that number of signatures is correct.
var signerAddrs = msg.GetSigners()
var signerAddrs = stdTx.GetSigners()
if len(sigs) != len(signerAddrs) {
return ctx,
sdk.ErrUnauthorized("wrong number of signers").Result(),
@ -78,7 +78,6 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
if chainID == "" {
chainID = viper.GetString("chain-id")
}
signBytes := StdSignBytes(ctx.ChainID(), accNums, sequences, fee, msg, memo)
// Check sig and nonce and collect signer accounts.
var signerAccs = make([]Account, len(signerAddrs))
@ -86,6 +85,7 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
signerAddr, sig := signerAddrs[i], sigs[i]
// check signature, return account with incremented nonce
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], sequences[i], fee, msgs, tx.GetMemo())
signerAcc, res := processSig(
ctx, am,
signerAddr, sig, signBytes,

View File

@ -65,22 +65,33 @@ func checkInvalidTx(t *testing.T, anteHandler sdk.AnteHandler, ctx sdk.Context,
fmt.Sprintf("Expected %v, got %v", sdk.ToABCICode(sdk.CodespaceRoot, code), result))
}
func newTestTx(ctx sdk.Context, msg sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee) sdk.Tx {
signBytes := StdSignBytes(ctx.ChainID(), accNums, seqs, fee, msg, "")
return newTestTxWithSignBytes(msg, privs, accNums, seqs, fee, signBytes, "")
func newTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee) sdk.Tx {
sigs := make([]StdSignature, len(privs))
for i, priv := range privs {
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], fee, msgs, "")
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: priv.Sign(signBytes), AccountNumber: accNums[i], Sequence: seqs[i]}
}
tx := NewStdTx(msgs, fee, sigs, "")
return tx
}
func newTestTxWithMemo(ctx sdk.Context, msg sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee, memo string) sdk.Tx {
signBytes := StdSignBytes(ctx.ChainID(), accNums, seqs, fee, msg, memo)
return newTestTxWithSignBytes(msg, privs, accNums, seqs, fee, signBytes, memo)
func newTestTxWithMemo(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee, memo string) sdk.Tx {
sigs := make([]StdSignature, len(privs))
for i, priv := range privs {
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], fee, msgs, memo)
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: priv.Sign(signBytes), AccountNumber: accNums[i], Sequence: seqs[i]}
}
tx := NewStdTx(msgs, fee, sigs, memo)
return tx
}
func newTestTxWithSignBytes(msg sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee, signBytes []byte, memo string) sdk.Tx {
// All signers sign over the same StdSignDoc. Should always create invalid signatures
func newTestTxWithSignBytes(msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee, signBytes []byte, memo string) sdk.Tx {
sigs := make([]StdSignature, len(privs))
for i, priv := range privs {
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: priv.Sign(signBytes), AccountNumber: accNums[i], Sequence: seqs[i]}
}
tx := NewStdTx(msg, fee, sigs, memo)
tx := NewStdTx(msgs, fee, sigs, memo)
return tx
}
@ -98,25 +109,36 @@ func TestAnteHandlerSigErrors(t *testing.T) {
// keys and addresses
priv1, addr1 := privAndAddr()
priv2, addr2 := privAndAddr()
priv3, addr3 := privAndAddr()
// msg and signatures
var tx sdk.Tx
msg := newTestMsg(addr1, addr2)
msg1 := newTestMsg(addr1, addr2)
msg2 := newTestMsg(addr1, addr3)
fee := newStdFee()
msgs := []sdk.Msg{msg1, msg2}
// test no signatures
privs, accNums, seqs := []crypto.PrivKey{}, []int64{}, []int64{}
tx = newTestTx(ctx, msg, privs, accNums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
// tx.GetSigners returns addresses in correct order: addr1, addr2, addr3
expectedSigners := []sdk.Address{addr1, addr2, addr3}
stdTx := tx.(StdTx)
assert.Equal(t, expectedSigners, stdTx.GetSigners())
// Check no signatures fails
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
// test num sigs dont match GetSigners
privs, accNums, seqs = []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
tx = newTestTx(ctx, msg, privs, accNums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
// test an unrecognized account
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{0, 0}
tx = newTestTx(ctx, msg, privs, accNums, seqs, fee)
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{0, 0, 0}
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnknownAddress)
// save the first account, but second is still unrecognized
@ -154,30 +176,34 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
msg := newTestMsg(addr1)
fee := newStdFee()
msgs := []sdk.Msg{msg}
// test good tx from one signer
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
// new tx from wrong account number
seqs = []int64{1}
tx = newTestTx(ctx, msg, privs, []int64{1}, seqs, fee)
tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
// from correct account number
seqs = []int64{1}
tx = newTestTx(ctx, msg, privs, []int64{0}, seqs, fee)
tx = newTestTx(ctx, msgs, privs, []int64{0}, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
// new tx with another signer and incorrect account numbers
msg = newTestMsg(addr1, addr2)
msg1 := newTestMsg(addr1, addr2)
msg2 := newTestMsg(addr2, addr1)
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{1, 0}, []int64{2, 0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
// correct account numbers
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{2, 0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
}
@ -195,6 +221,7 @@ func TestAnteHandlerSequences(t *testing.T) {
// keys and addresses
priv1, addr1 := privAndAddr()
priv2, addr2 := privAndAddr()
priv3, addr3 := privAndAddr()
// set the accounts
acc1 := mapper.NewAccountWithAddress(ctx, addr1)
@ -203,15 +230,20 @@ func TestAnteHandlerSequences(t *testing.T) {
acc2 := mapper.NewAccountWithAddress(ctx, addr2)
acc2.SetCoins(newCoins())
mapper.SetAccount(ctx, acc2)
acc3 := mapper.NewAccountWithAddress(ctx, addr3)
acc3.SetCoins(newCoins())
mapper.SetAccount(ctx, acc3)
// msg and signatures
var tx sdk.Tx
msg := newTestMsg(addr1)
fee := newStdFee()
msgs := []sdk.Msg{msg}
// test good tx from one signer
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
// test sending it again fails (replay protection)
@ -219,13 +251,16 @@ func TestAnteHandlerSequences(t *testing.T) {
// fix sequence, should pass
seqs = []int64{1}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
// new tx with another signer and correct sequences
msg = newTestMsg(addr1, addr2)
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{2, 0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
msg1 := newTestMsg(addr1, addr2)
msg2 := newTestMsg(addr3, addr1)
msgs = []sdk.Msg{msg1, msg2}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{2, 0, 0}
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
// replay fails
@ -233,18 +268,20 @@ func TestAnteHandlerSequences(t *testing.T) {
// tx from just second signer with incorrect sequence fails
msg = newTestMsg(addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{1}, []int64{0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
// fix the sequence and it passes
tx = newTestTx(ctx, msg, []crypto.PrivKey{priv2}, []int64{1}, []int64{1}, fee)
tx = newTestTx(ctx, msgs, []crypto.PrivKey{priv2}, []int64{1}, []int64{1}, fee)
checkValidTx(t, anteHandler, ctx, tx)
// another tx from both of them that passes
msg = newTestMsg(addr1, addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{3, 2}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
}
@ -271,9 +308,10 @@ func TestAnteHandlerFees(t *testing.T) {
msg := newTestMsg(addr1)
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
fee := newStdFee()
msgs := []sdk.Msg{msg}
// signer does not have enough funds to pay the fee
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds)
acc1.SetCoins(sdk.Coins{sdk.NewCoin("atom", 149)})
@ -314,22 +352,73 @@ func TestAnteHandlerMemoGas(t *testing.T) {
fee := NewStdFee(0, sdk.NewCoin("atom", 0))
// tx does not have enough gas
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas)
// tx with memo doesn't have enough gas
fee = NewStdFee(1001, sdk.NewCoin("atom", 0))
tx = newTestTxWithMemo(ctx, msg, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas)
// memo too large
fee = NewStdFee(2001, sdk.NewCoin("atom", 0))
tx = newTestTxWithMemo(ctx, msg, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsdabcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeMemoTooLarge)
// tx with memo has enough gas
fee = NewStdFee(1100, sdk.NewCoin("atom", 0))
tx = newTestTxWithMemo(ctx, msg, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd")
checkValidTx(t, anteHandler, ctx, tx)
}
func TestAnteHandlerMultiSigner(t *testing.T) {
// setup
ms, capKey, capKey2 := setupMultiStore()
cdc := wire.NewCodec()
RegisterBaseAccount(cdc)
mapper := NewAccountMapper(cdc, capKey, &BaseAccount{})
feeCollector := NewFeeCollectionKeeper(cdc, capKey2)
anteHandler := NewAnteHandler(mapper, feeCollector)
ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger())
// keys and addresses
priv1, addr1 := privAndAddr()
priv2, addr2 := privAndAddr()
priv3, addr3 := privAndAddr()
// set the accounts
acc1 := mapper.NewAccountWithAddress(ctx, addr1)
acc1.SetCoins(newCoins())
mapper.SetAccount(ctx, acc1)
acc2 := mapper.NewAccountWithAddress(ctx, addr2)
acc2.SetCoins(newCoins())
mapper.SetAccount(ctx, acc2)
acc3 := mapper.NewAccountWithAddress(ctx, addr3)
acc3.SetCoins(newCoins())
mapper.SetAccount(ctx, acc3)
// set up msgs and fee
var tx sdk.Tx
msg1 := newTestMsg(addr1, addr2)
msg2 := newTestMsg(addr3, addr1)
msg3 := newTestMsg(addr2, addr3)
msgs := []sdk.Msg{msg1, msg2, msg3}
fee := newStdFee()
// signers in order
privs, accnums, seqs := []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{0, 0, 0}
tx = newTestTxWithMemo(ctx, msgs, privs, accnums, seqs, fee, "Check signers are in expected order and different account numbers works")
checkValidTx(t, anteHandler, ctx, tx)
// change sequence numbers
tx = newTestTx(ctx, []sdk.Msg{msg1}, []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{1, 1}, fee)
checkValidTx(t, anteHandler, ctx, tx)
tx = newTestTx(ctx, []sdk.Msg{msg2}, []crypto.PrivKey{priv3, priv1}, []int64{2, 0}, []int64{1, 2}, fee)
checkValidTx(t, anteHandler, ctx, tx)
// expected seqs = [3, 2, 2]
tx = newTestTxWithMemo(ctx, msgs, privs, accnums, []int64{3, 2, 2}, fee, "Check signers are in expected order and different account numbers and sequence numbers works")
checkValidTx(t, anteHandler, ctx, tx)
}
@ -357,6 +446,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
var tx sdk.Tx
msg := newTestMsg(addr1)
msgs := []sdk.Msg{msg}
fee := newStdFee()
fee2 := newStdFee()
fee2.Gas += 100
@ -365,7 +455,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
// test good tx and signBytes
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
chainID := ctx.ChainID()
@ -374,26 +464,26 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
cases := []struct {
chainID string
accnums []int64
seqs []int64
accnum int64
seq int64
fee StdFee
msg sdk.Msg
msgs []sdk.Msg
code sdk.CodeType
}{
{chainID2, []int64{0}, []int64{1}, fee, msg, codeUnauth}, // test wrong chain_id
{chainID, []int64{0}, []int64{2}, fee, msg, codeUnauth}, // test wrong seqs
{chainID, []int64{0}, []int64{1, 2}, fee, msg, codeUnauth}, // test wrong seqs
{chainID, []int64{1}, []int64{1}, fee, msg, codeUnauth}, // test wrong accnum
{chainID, []int64{0}, []int64{1}, fee, newTestMsg(addr2), codeUnauth}, // test wrong msg
{chainID, []int64{0}, []int64{1}, fee2, msg, codeUnauth}, // test wrong fee
{chainID, []int64{0}, []int64{1}, fee3, msg, codeUnauth}, // test wrong fee
{chainID2, 0, 1, fee, msgs, codeUnauth}, // test wrong chain_id
{chainID, 0, 2, fee, msgs, codeUnauth}, // test wrong seqs
{chainID, 1, 1, fee, msgs, codeUnauth}, // test wrong accnum
{chainID, 0, 1, fee, []sdk.Msg{newTestMsg(addr2)}, codeUnauth}, // test wrong msg
{chainID, 0, 1, fee2, msgs, codeUnauth}, // test wrong fee
{chainID, 0, 1, fee3, msgs, codeUnauth}, // test wrong fee
}
privs, seqs = []crypto.PrivKey{priv1}, []int64{1}
for _, cs := range cases {
tx := newTestTxWithSignBytes(
msg, privs, accnums, seqs, fee,
StdSignBytes(cs.chainID, cs.accnums, cs.seqs, cs.fee, cs.msg, ""),
msgs, privs, accnums, seqs, fee,
StdSignBytes(cs.chainID, cs.accnum, cs.seq, cs.fee, cs.msgs, ""),
"",
)
checkInvalidTx(t, anteHandler, ctx, tx, cs.code)
@ -401,13 +491,14 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
// test wrong signer if public key exist
privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{0}, []int64{1}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
// test wrong signer if public doesn't exist
msg = newTestMsg(addr2)
msgs = []sdk.Msg{msg}
privs, accnums, seqs = []crypto.PrivKey{priv1}, []int64{1}, []int64{0}
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
}
@ -438,9 +529,10 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
// test good tx and set public key
msg := newTestMsg(addr1)
msgs := []sdk.Msg{msg}
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
fee := newStdFee()
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
checkValidTx(t, anteHandler, ctx, tx)
acc1 = mapper.GetAccount(ctx, addr1)
@ -448,7 +540,8 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
// test public key not found
msg = newTestMsg(addr2)
tx = newTestTx(ctx, msg, privs, []int64{1}, seqs, fee)
msgs = []sdk.Msg{msg}
tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee)
sigs := tx.(StdTx).GetSignatures()
sigs[0].PubKey = nil
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
@ -457,7 +550,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
assert.Nil(t, acc2.GetPubKey())
// test invalid signature and public key
tx = newTestTx(ctx, msg, privs, []int64{1}, seqs, fee)
tx = newTestTx(ctx, msgs, privs, []int64{1}, seqs, fee)
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
acc2 = mapper.GetAccount(ctx, addr2)

View File

@ -62,7 +62,7 @@ func TestMsgChangePubKey(t *testing.T) {
assert.Equal(t, acc1, res1.(*auth.BaseAccount))
// Run a CheckDeliver
SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{0}, true, priv1)
SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, true, priv1)
// Check balances
CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 67)})
@ -78,19 +78,19 @@ func TestMsgChangePubKey(t *testing.T) {
acc2 := mapp.AccountMapper.GetAccount(ctxDeliver, addr1)
// send a MsgChangePubKey
SignCheckDeliver(t, mapp.BaseApp, changePubKeyMsg, []int64{0}, []int64{1}, true, priv1)
SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{changePubKeyMsg}, []int64{0}, []int64{1}, true, priv1)
acc2 = mapp.AccountMapper.GetAccount(ctxDeliver, addr1)
assert.True(t, priv2.PubKey().Equals(acc2.GetPubKey()))
// signing a SendMsg with the old privKey should be an auth error
mapp.BeginBlock(abci.RequestBeginBlock{})
tx := GenTx(sendMsg1, []int64{0}, []int64{2}, priv1)
tx := GenTx([]sdk.Msg{sendMsg1}, []int64{0}, []int64{2}, priv1)
res := mapp.Deliver(tx)
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
// resigning the tx with the new correct priv key should work
SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{2}, true, priv2)
SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{2}, true, priv2)
// Check balances
CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})

View File

@ -33,7 +33,7 @@ func CheckBalance(t *testing.T, app *App, addr sdk.Address, exp sdk.Coins) {
}
// generate a signed transaction
func GenTx(msg sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) auth.StdTx {
func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) auth.StdTx {
// make the transaction free
fee := auth.StdFee{
@ -46,26 +46,26 @@ func GenTx(msg sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25
for i, p := range priv {
sigs[i] = auth.StdSignature{
PubKey: p.PubKey(),
Signature: p.Sign(auth.StdSignBytes(chainID, accnums, seq, fee, msg, memo)),
Signature: p.Sign(auth.StdSignBytes(chainID, accnums[i], seq[i], fee, msgs, memo)),
AccountNumber: accnums[i],
Sequence: seq[i],
}
}
return auth.NewStdTx(msg, fee, sigs, memo)
return auth.NewStdTx(msgs, fee, sigs, memo)
}
// check a transaction result
func SignCheck(t *testing.T, app *baseapp.BaseApp, msg sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result {
tx := GenTx(msg, accnums, seq, priv...)
func SignCheck(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result {
tx := GenTx(msgs, accnums, seq, priv...)
res := app.Check(tx)
return res
}
// simulate a block
func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msg sdk.Msg, accnums []int64, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
// Sign the tx
tx := GenTx(msg, accnums, seq, priv...)
tx := GenTx(msgs, accnums, seq, priv...)
// Run a Check
res := app.Check(tx)

View File

@ -12,15 +12,15 @@ var _ sdk.Tx = (*StdTx)(nil)
// StdTx is a standard way to wrap a Msg with Fee and Signatures.
// NOTE: the first signature is the FeePayer (Signatures must not be nil).
type StdTx struct {
Msg sdk.Msg `json:"msg"`
Msgs []sdk.Msg `json:"msg"`
Fee StdFee `json:"fee"`
Signatures []StdSignature `json:"signatures"`
Memo string `json:"memo"`
}
func NewStdTx(msg sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx {
func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx {
return StdTx{
Msg: msg,
Msgs: msgs,
Fee: fee,
Signatures: sigs,
Memo: memo,
@ -28,12 +28,32 @@ func NewStdTx(msg sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx {
}
//nolint
func (tx StdTx) GetMsg() sdk.Msg { return tx.Msg }
func (tx StdTx) GetMsgs() []sdk.Msg { return tx.Msgs }
// GetSigners returns the addresses that must sign the transaction.
// Addresses are returned in a determistic order.
// They are accumulated from the GetSigners method for each Msg
// in the order they appear in tx.GetMsgs().
// Duplicate addresses will be ommitted.
func (tx StdTx) GetSigners() []sdk.Address {
seen := map[string]bool{}
var signers []sdk.Address
for _, msg := range tx.GetMsgs() {
for _, addr := range msg.GetSigners() {
if !seen[addr.String()] {
signers = append(signers, addr)
seen[addr.String()] = true
}
}
}
return signers
}
//nolint
func (tx StdTx) GetMemo() string { return tx.Memo }
// Signatures returns the signature of signers who signed the Msg.
// GetSignatures returns the signature of signers who signed the Msg.
// CONTRACT: Length returned is same as length of
// pubkeys returned from MsgKeySigners, and the order
// matches.
@ -46,7 +66,7 @@ func (tx StdTx) GetSignatures() []StdSignature { return tx.Signatures }
// for the transactions. It's the first address returned by msg.GetSigners().
// If GetSigners() is empty, this panics.
func FeePayer(tx sdk.Tx) sdk.Address {
return tx.GetMsg().GetSigners()[0]
return tx.GetMsgs()[0].GetSigners()[0]
}
//__________________________________________________________
@ -90,24 +110,29 @@ func (fee StdFee) Bytes() []byte {
// and the Sequence numbers for each signature (prevent
// inchain replay and enforce tx ordering per account).
type StdSignDoc struct {
ChainID string `json:"chain_id"`
AccountNumbers []int64 `json:"account_numbers"`
Sequences []int64 `json:"sequences"`
Fee json.RawMessage `json:"fee"`
Msg json.RawMessage `json:"msg"`
Memo string `json:"memo"`
ChainID string `json:"chain_id"`
AccountNumber int64 `json:"account_number"`
Sequence int64 `json:"sequence"`
FeeBytes []byte `json:"fee_bytes"`
MsgsBytes []byte `json:"msg_bytes"`
Memo string `json:"memo"`
}
// StdSignBytes returns the bytes to sign for a transaction.
// TODO: change the API to just take a chainID and StdTx ?
func StdSignBytes(chainID string, accnums []int64, sequences []int64, fee StdFee, msg sdk.Msg, memo string) []byte {
func StdSignBytes(chainID string, accnum int64, sequence int64, fee StdFee, msgs []sdk.Msg, memo string) []byte {
var msgBytes []byte
for _, msg := range msgs {
msgBytes = append(msgBytes, msg.GetSignBytes()...)
}
bz, err := json.Marshal(StdSignDoc{
ChainID: chainID,
AccountNumbers: accnums,
Sequences: sequences,
Fee: json.RawMessage(fee.Bytes()),
Msg: json.RawMessage(msg.GetSignBytes()),
Memo: memo,
ChainID: chainID,
AccountNumber: accnum,
Sequence: sequence,
FeeBytes: fee.Bytes(),
MsgsBytes: msgBytes,
Memo: memo,
})
if err != nil {
panic(err)
@ -119,17 +144,17 @@ func StdSignBytes(chainID string, accnums []int64, sequences []int64, fee StdFee
// a Msg with the other requirements for a StdSignDoc before
// it is signed. For use in the CLI.
type StdSignMsg struct {
ChainID string
AccountNumbers []int64
Sequences []int64
Fee StdFee
Msg sdk.Msg
Memo string
ChainID string
AccountNumber int64
Sequence int64
Fee StdFee
Msgs []sdk.Msg
Memo string
}
// get message bytes
func (msg StdSignMsg) Bytes() []byte {
return StdSignBytes(msg.ChainID, msg.AccountNumbers, msg.Sequences, msg.Fee, msg.Msg, msg.Memo)
return StdSignBytes(msg.ChainID, msg.AccountNumber, msg.Sequence, msg.Fee, msg.Msgs, msg.Memo)
}
// Standard Signature

View File

@ -19,12 +19,12 @@ import (
func TestStdTx(t *testing.T) {
priv := crypto.GenPrivKeyEd25519()
addr := priv.PubKey().Address()
msg := sdk.NewTestMsg(addr)
msgs := []sdk.Msg{sdk.NewTestMsg(addr)}
fee := newStdFee()
sigs := []StdSignature{}
tx := NewStdTx(msg, fee, sigs, "")
assert.Equal(t, msg, tx.GetMsg())
tx := NewStdTx(msgs, fee, sigs, "")
assert.Equal(t, msgs, tx.GetMsgs())
assert.Equal(t, sigs, tx.GetSignatures())
feePayer := FeePayer(tx)

View File

@ -107,25 +107,25 @@ func TestMsgSendWithAccounts(t *testing.T) {
assert.Equal(t, acc, res1.(*auth.BaseAccount))
// Run a CheckDeliver
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, true, priv1)
// Check balances
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
// Delivering again should cause replay error
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{0}, false, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1, sendMsg2}, []int64{0}, []int64{0}, false, priv1)
// bumping the txnonce number without resigning should be an auth error
mapp.BeginBlock(abci.RequestBeginBlock{})
tx := mock.GenTx(sendMsg1, []int64{0}, []int64{0}, priv1)
tx := mock.GenTx([]sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, priv1)
tx.Signatures[0].Sequence = 1
res := mapp.Deliver(tx)
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
// resigning the tx with the bumped sequence should work
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{1}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1, sendMsg2}, []int64{0}, []int64{1}, true, priv1)
}
func TestMsgSendMultipleOut(t *testing.T) {
@ -145,7 +145,7 @@ func TestMsgSendMultipleOut(t *testing.T) {
mock.SetGenesis(mapp, accs)
// Simulate a Block
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg2, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg2}, []int64{0}, []int64{0}, true, priv1)
// Check balances
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
@ -173,7 +173,7 @@ func TestSengMsgMultipleInOut(t *testing.T) {
mock.SetGenesis(mapp, accs)
// CheckDeliver
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg3, []int64{0, 2}, []int64{0, 0}, true, priv1, priv4)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg3}, []int64{0, 2}, []int64{0, 0}, true, priv1, priv4)
// Check balances
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
@ -194,14 +194,14 @@ func TestMsgSendDependent(t *testing.T) {
mock.SetGenesis(mapp, accs)
// CheckDeliver
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg1, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg1}, []int64{0}, []int64{0}, true, priv1)
// Check balances
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
// Simulate a Block
mock.SignCheckDeliver(t, mapp.BaseApp, sendMsg4, []int64{1}, []int64{0}, true, priv2)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{sendMsg4}, []int64{1}, []int64{0}, true, priv2)
// Check balances
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)})

View File

@ -47,7 +47,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command {
// build and sign the transaction, then broadcast to Tendermint
msg := client.BuildMsg(from, to, coins)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -96,7 +96,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreCont
// sign
ctx = ctx.WithAccountNumber(m.AccountNumber)
ctx = ctx.WithSequence(m.Sequence)
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc)
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, []sdk.Msg{msg}, cdc)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))

View File

@ -71,10 +71,10 @@ func TestIBCMsgs(t *testing.T) {
Sequence: 0,
}
mock.SignCheckDeliver(t, mapp.BaseApp, transferMsg, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{transferMsg}, []int64{0}, []int64{0}, true, priv1)
mock.CheckBalance(t, mapp, addr1, emptyCoins)
mock.SignCheckDeliver(t, mapp.BaseApp, transferMsg, []int64{0}, []int64{1}, false, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, receiveMsg, []int64{0}, []int64{2}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{transferMsg}, []int64{0}, []int64{1}, false, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{receiveMsg}, []int64{0}, []int64{2}, true, priv1)
mock.CheckBalance(t, mapp, addr1, coins)
mock.SignCheckDeliver(t, mapp.BaseApp, receiveMsg, []int64{0}, []int64{3}, false, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{receiveMsg}, []int64{0}, []int64{2}, false, priv1)
}

View File

@ -43,7 +43,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command {
}
// get password
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -189,7 +189,7 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b
}
ctx := context.NewCoreContextFromViper().WithSequence(sequence)
res, err := ctx.SignAndBuild(ctx.FromAddressName, passphrase, msg, c.cdc)
res, err := ctx.SignAndBuild(ctx.FromAddressName, passphrase, []sdk.Msg{msg}, c.cdc)
if err != nil {
panic(err)
}

View File

@ -85,7 +85,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.Core
// sign
ctx = ctx.WithAccountNumber(m.AccountNumber)
ctx = ctx.WithSequence(m.Sequence)
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc)
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, []sdk.Msg{msg}, cdc)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))

View File

@ -92,7 +92,7 @@ func TestSlashingMsgs(t *testing.T) {
createValidatorMsg := stake.NewMsgCreateValidator(
addr1, priv1.PubKey(), bondCoin, description,
)
mock.SignCheckDeliver(t, mapp.BaseApp, createValidatorMsg, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
mapp.BeginBlock(abci.RequestBeginBlock{})
@ -106,6 +106,6 @@ func TestSlashingMsgs(t *testing.T) {
checkValidatorSigningInfo(t, mapp, keeper, addr1, false)
// unrevoke should fail with unknown validator
res := mock.SignCheck(t, mapp.BaseApp, unrevokeMsg, []int64{0}, []int64{1}, priv1)
res := mock.SignCheck(t, mapp.BaseApp, []sdk.Msg{unrevokeMsg}, []int64{0}, []int64{1}, priv1)
require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeInvalidValidator), res.Code)
}

View File

@ -29,7 +29,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command {
msg := slashing.NewMsgUnrevoke(validatorAddr)
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -117,7 +117,7 @@ func TestStakeMsgs(t *testing.T) {
createValidatorMsg := NewMsgCreateValidator(
addr1, priv1.PubKey(), bondCoin, description,
)
mock.SignCheckDeliver(t, mapp.BaseApp, createValidatorMsg, []int64{0}, []int64{0}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{createValidatorMsg}, []int64{0}, []int64{0}, true, priv1)
mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
mapp.BeginBlock(abci.RequestBeginBlock{})
@ -134,7 +134,7 @@ func TestStakeMsgs(t *testing.T) {
description = NewDescription("bar_moniker", "", "", "")
editValidatorMsg := NewMsgEditValidator(addr1, description)
mock.SignCheckDeliver(t, mapp.BaseApp, editValidatorMsg, []int64{0}, []int64{1}, true, priv1)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{editValidatorMsg}, []int64{0}, []int64{1}, true, priv1)
validator = checkValidator(t, mapp, keeper, addr1, true)
require.Equal(t, description, validator.Description)
@ -143,7 +143,7 @@ func TestStakeMsgs(t *testing.T) {
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin})
delegateMsg := NewMsgDelegate(addr2, addr1, bondCoin)
mock.SignCheckDeliver(t, mapp.BaseApp, delegateMsg, []int64{1}, []int64{0}, true, priv2)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{delegateMsg}, []int64{1}, []int64{0}, true, priv2)
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
checkDelegation(t, mapp, keeper, addr2, addr1, true, sdk.NewRat(10))
@ -151,7 +151,7 @@ func TestStakeMsgs(t *testing.T) {
// Unbond
unbondMsg := NewMsgUnbond(addr2, addr1, "MAX")
mock.SignCheckDeliver(t, mapp.BaseApp, unbondMsg, []int64{1}, []int64{1}, true, priv2)
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{unbondMsg}, []int64{1}, []int64{1}, true, priv2)
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin})
checkDelegation(t, mapp, keeper, addr2, addr1, false, sdk.Rat{})
}

View File

@ -50,7 +50,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command {
msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description)
// build and sign the transaction, then broadcast to Tendermint
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}
@ -89,7 +89,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command {
// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}
@ -126,7 +126,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}
@ -174,7 +174,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
// build and sign the transaction, then broadcast to Tendermint
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
if err != nil {
return err
}

View File

@ -134,7 +134,7 @@ func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx conte
ctx = ctx.WithSequence(m.Sequence)
m.Sequence++
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc)
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, []sdk.Msg{msg}, cdc)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))