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:
parent
3fa68249eb
commit
f049a56376
|
@ -7,6 +7,8 @@
|
||||||
BREAKING CHANGES
|
BREAKING CHANGES
|
||||||
* Change default ports from 466xx to 266xx
|
* Change default ports from 466xx to 266xx
|
||||||
* AltBytes renamed to Memo, now a string, max 100 characters, costs a bit of gas
|
* 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
|
FEATURES
|
||||||
* [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag
|
* [gaiacli] You can now attach a simple text-only memo to any transaction, with the `--memo` flag
|
||||||
|
|
|
@ -64,11 +64,8 @@ type BaseApp struct {
|
||||||
// checkState is set on initialization and reset on Commit.
|
// checkState is set on initialization and reset on Commit.
|
||||||
// deliverState is set in InitChain and BeginBlock and cleared on Commit.
|
// deliverState is set in InitChain and BeginBlock and cleared on Commit.
|
||||||
// See methods setCheckState and setDeliverState.
|
// 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
|
checkState *state // for CheckTx
|
||||||
deliverState *state // for DeliverTx
|
deliverState *state // for DeliverTx
|
||||||
valUpdates []abci.Validator // cached validator changes from DeliverTx
|
|
||||||
signedValidators []abci.SigningValidator // absent validators from begin block
|
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 {
|
if app.deliverState == nil {
|
||||||
app.setDeliverState(req.Header)
|
app.setDeliverState(req.Header)
|
||||||
}
|
}
|
||||||
app.valUpdates = nil
|
|
||||||
if app.beginBlocker != nil {
|
if app.beginBlocker != nil {
|
||||||
res = app.beginBlocker(app.deliverState.ctx, req)
|
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)
|
result = app.runTx(runTxModeDeliver, txBytes, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// After-handler hooks.
|
// Even though the Result.Code is not OK, there are still effects,
|
||||||
if result.IsOK() {
|
// namely fee deductions and sequence incrementing.
|
||||||
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.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the blockchain engine (i.e. Tendermint).
|
// Tell the blockchain engine (i.e. Tendermint).
|
||||||
return abci.ResponseDeliverTx{
|
return abci.ResponseDeliverTx{
|
||||||
|
@ -484,16 +475,18 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Get the Msg.
|
// Get the Msg.
|
||||||
var msg = tx.GetMsg()
|
var msgs = tx.GetMsgs()
|
||||||
if msg == nil {
|
if msgs == nil || len(msgs) == 0 {
|
||||||
return sdk.ErrInternal("Tx.GetMsg() returned nil").Result()
|
return sdk.ErrInternal("Tx.GetMsgs() must return at least one message in list").Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the Msg.
|
for _, msg := range msgs {
|
||||||
err := msg.ValidateBasic()
|
// Validate the Msg
|
||||||
if err != nil {
|
err := msg.ValidateBasic()
|
||||||
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
|
if err != nil {
|
||||||
return err.Result()
|
err = err.WithDefaultCodespace(sdk.CodespaceRoot)
|
||||||
|
return err.Result()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the context
|
// 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
|
// Get the correct cache
|
||||||
var msCache sdk.CacheMultiStore
|
var msCache sdk.CacheMultiStore
|
||||||
if mode == runTxModeCheck || mode == runTxModeSimulate {
|
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)
|
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 = handler(ctx, msg)
|
||||||
result.GasUsed = ctx.GasMeter().GasConsumed()
|
|
||||||
|
// 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
|
// 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() {
|
if mode != runTxModeSimulate && result.IsOK() {
|
||||||
msCache.Write()
|
msCache.Write()
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
finalResult.Log = strings.Join(logs, "\n")
|
||||||
|
|
||||||
|
return finalResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ABCI
|
// Implements ABCI
|
||||||
func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
|
func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
|
||||||
if app.endBlocker != nil {
|
if app.endBlocker != nil {
|
||||||
res = app.endBlocker(app.deliverState.ctx, req)
|
res = app.endBlocker(app.deliverState.ctx, req)
|
||||||
} else {
|
|
||||||
res.ValidatorUpdates = app.valUpdates
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package baseapp
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ func newBaseApp(name string) *BaseApp {
|
||||||
logger := defaultLogger()
|
logger := defaultLogger()
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
codec := wire.NewCodec()
|
codec := wire.NewCodec()
|
||||||
wire.RegisterCrypto(codec)
|
auth.RegisterBaseAccount(codec)
|
||||||
return NewBaseApp(name, codec, logger, db)
|
return NewBaseApp(name, codec, logger, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +263,8 @@ type testTx struct {
|
||||||
const msgType2 = "testTx"
|
const msgType2 = "testTx"
|
||||||
|
|
||||||
func (tx testTx) Type() string { return msgType2 }
|
func (tx testTx) Type() string { return msgType2 }
|
||||||
func (tx testTx) GetMsg() sdk.Msg { return tx }
|
|
||||||
func (tx testTx) GetMemo() string { return "" }
|
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) GetSignBytes() []byte { return nil }
|
||||||
func (tx testTx) GetSigners() []sdk.Address { return nil }
|
func (tx testTx) GetSigners() []sdk.Address { return nil }
|
||||||
func (tx testTx) GetSignatures() []auth.StdSignature { return nil }
|
func (tx testTx) GetSignatures() []auth.StdSignature { return nil }
|
||||||
|
@ -547,8 +548,8 @@ type testUpdatePowerTx struct {
|
||||||
const msgType = "testUpdatePowerTx"
|
const msgType = "testUpdatePowerTx"
|
||||||
|
|
||||||
func (tx testUpdatePowerTx) Type() string { return msgType }
|
func (tx testUpdatePowerTx) Type() string { return msgType }
|
||||||
func (tx testUpdatePowerTx) GetMsg() sdk.Msg { return tx }
|
|
||||||
func (tx testUpdatePowerTx) GetMemo() string { return "" }
|
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) GetSignBytes() []byte { return nil }
|
||||||
func (tx testUpdatePowerTx) ValidateBasic() sdk.Error { return nil }
|
func (tx testUpdatePowerTx) ValidateBasic() sdk.Error { return nil }
|
||||||
func (tx testUpdatePowerTx) GetSigners() []sdk.Address { 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 {
|
func randPower() int64 {
|
||||||
return cmn.RandInt64()
|
return cmn.RandInt64()
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ func (ctx CoreContext) GetFromAddress() (from sdk.Address, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign and build the transaction from the msg
|
// 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
|
// build the Sign Messsage from the Standard Message
|
||||||
chainID := ctx.ChainID
|
chainID := ctx.ChainID
|
||||||
|
@ -126,12 +126,12 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w
|
||||||
memo := ctx.Memo
|
memo := ctx.Memo
|
||||||
|
|
||||||
signMsg := auth.StdSignMsg{
|
signMsg := auth.StdSignMsg{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
AccountNumbers: []int64{accnum},
|
AccountNumber: int64(accnum),
|
||||||
Sequences: []int64{sequence},
|
Sequence: int64(sequence),
|
||||||
Msg: msg,
|
Msgs: msgs,
|
||||||
Memo: memo,
|
Memo: memo,
|
||||||
Fee: auth.NewStdFee(ctx.Gas, sdk.Coin{}), // TODO run simulate to estimate gas?
|
Fee: auth.NewStdFee(ctx.Gas, sdk.Coin{}), // TODO run simulate to estimate gas?
|
||||||
}
|
}
|
||||||
|
|
||||||
keybase, err := keys.GetKeyBase()
|
keybase, err := keys.GetKeyBase()
|
||||||
|
@ -154,13 +154,13 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msg sdk.Msg, cdc *w
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// marshal bytes
|
// marshal bytes
|
||||||
tx := auth.NewStdTx(signMsg.Msg, signMsg.Fee, sigs, memo)
|
tx := auth.NewStdTx(signMsg.Msgs, signMsg.Fee, sigs, memo)
|
||||||
|
|
||||||
return cdc.MarshalBinary(tx)
|
return cdc.MarshalBinary(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign and build the transaction from the msg
|
// 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)
|
ctx, err = EnsureAccountNumber(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -177,7 +177,7 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msg sdk.Msg, cdc *w
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
txBytes, err := ctx.SignAndBuild(name, passphrase, msg, cdc)
|
txBytes, err := ctx.SignAndBuild(name, passphrase, msgs, cdc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ func GaiaAppGenTx(cdc *wire.Codec, pk crypto.PubKey, genTxConfig config.GenTx) (
|
||||||
}
|
}
|
||||||
|
|
||||||
cliPrint = json.RawMessage(bz)
|
cliPrint = json.RawMessage(bz)
|
||||||
|
|
||||||
appGenTx, _, validator, err = GaiaAppGenTxNF(cdc, pk, addr, genTxConfig.Name, genTxConfig.Overwrite)
|
appGenTx, _, validator, err = GaiaAppGenTxNF(cdc, pk, addr, genTxConfig.Name, genTxConfig.Overwrite)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ The design of the Cosmos SDK is based on the principles of "capabilities systems
|
||||||
## Tx & Msg
|
## Tx & Msg
|
||||||
|
|
||||||
The SDK distinguishes between transactions (Tx) and messages
|
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
|
### Messages
|
||||||
|
|
||||||
|
@ -92,13 +92,12 @@ func (msg MsgIssue) GetSigners() []sdk.Address {
|
||||||
|
|
||||||
### Transactions
|
### Transactions
|
||||||
|
|
||||||
A transaction is a message with additional information for authentication:
|
A transaction is a list of messages with additional information for authentication:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Tx interface {
|
type Tx interface {
|
||||||
|
|
||||||
GetMsg() Msg
|
GetMsgs() Msg
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -90,17 +90,17 @@ func TestMsgQuiz(t *testing.T) {
|
||||||
assert.Equal(t, acc1, res1)
|
assert.Equal(t, acc1, res1)
|
||||||
|
|
||||||
// Set the trend, submit a really cool quiz and check for reward
|
// 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, []sdk.Msg{setTrendMsg1}, []int64{0}, []int64{0}, true, priv1)
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg1, []int64{0}, []int64{1}, true, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{1}, true, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 69)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg2, []int64{0}, []int64{2}, false, priv1) // result without reward
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg2}, []int64{0}, []int64{2}, false, priv1) // result without reward
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 69)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(69)}})
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg1, []int64{0}, []int64{3}, true, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{quizMsg1}, []int64{0}, []int64{3}, true, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("icecold", 138)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, setTrendMsg2, []int64{0}, []int64{4}, true, priv1) // reset the trend
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{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.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{sdk.NewCoin("icecold", 138)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"icecold", sdk.NewInt(138)}})
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, quizMsg2, []int64{0}, []int64{6}, true, priv1) // earlier answer now relavent again
|
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{sdk.NewCoin("badvibesonly", 69), sdk.NewCoin("icecold", 138)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"badvibesonly", sdk.NewInt(69)}, {"icecold", sdk.NewInt(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{setTrendMsg3}, []int64{0}, []int64{7}, false, priv1) // expect to fail to set the trend to something which is not cool
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/wire"
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
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)
|
name := viper.GetString(client.FlagName)
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ func SetTrendTxCmd(cdc *wire.Codec) *cobra.Command {
|
||||||
msg := cool.NewMsgSetTrend(from, args[0])
|
msg := cool.NewMsgSetTrend(from, args[0])
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,13 +72,13 @@ func TestMsgMine(t *testing.T) {
|
||||||
|
|
||||||
// Mine and check for reward
|
// Mine and check for reward
|
||||||
mineMsg1 := GenerateMsgMine(addr1, 1, 2)
|
mineMsg1 := GenerateMsgMine(addr1, 1, 2)
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg1, []int64{0}, []int64{0}, true, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg1}, []int64{0}, []int64{0}, true, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 1)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(1)}})
|
||||||
// Mine again and check for reward
|
// Mine again and check for reward
|
||||||
mineMsg2 := GenerateMsgMine(addr1, 2, 3)
|
mineMsg2 := GenerateMsgMine(addr1, 2, 3)
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg2, []int64{0}, []int64{1}, true, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, true, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 2)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
|
||||||
// Mine again - should be invalid
|
// Mine again - should be invalid
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, mineMsg2, []int64{0}, []int64{1}, false, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{mineMsg2}, []int64{0}, []int64{1}, false, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("pow", 2)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"pow", sdk.NewInt(2)}})
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/client/context"
|
"github.com/cosmos/cosmos-sdk/client/context"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
|
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/wire"
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||||
)
|
)
|
||||||
|
@ -48,7 +49,7 @@ func MineCmd(cdc *wire.Codec) *cobra.Command {
|
||||||
name := ctx.FromAddressName
|
name := ctx.FromAddressName
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func UnbondTxCmd(cdc *wire.Codec) *cobra.Command {
|
||||||
|
|
||||||
func sendMsg(cdc *wire.Codec, msg sdk.Msg) error {
|
func sendMsg(cdc *wire.Codec, msg sdk.Msg) error {
|
||||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package simplestake
|
package simplestake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
abci "github.com/tendermint/abci/types"
|
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/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 {
|
func handleMsgBond(ctx sdk.Context, k Keeper, msg MsgBond) sdk.Result {
|
||||||
power, err := k.Bond(ctx, msg.Address, msg.PubKey, msg.Stake)
|
// Removed ValidatorSet from result because it does not get used.
|
||||||
if err != nil {
|
// TODO: Implement correct bond/unbond handling
|
||||||
return err.Result()
|
|
||||||
}
|
|
||||||
|
|
||||||
valSet := abci.Validator{
|
|
||||||
PubKey: tmtypes.TM2PB.PubKey(msg.PubKey),
|
|
||||||
Power: power,
|
|
||||||
}
|
|
||||||
|
|
||||||
return sdk.Result{
|
return sdk.Result{
|
||||||
Code: sdk.ABCICodeOK,
|
Code: sdk.ABCICodeOK,
|
||||||
ValidatorUpdates: abci.Validators{valSet},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgUnbond(ctx sdk.Context, k Keeper, msg MsgUnbond) sdk.Result {
|
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{
|
return sdk.Result{
|
||||||
Code: sdk.ABCICodeOK,
|
Code: sdk.ABCICodeOK,
|
||||||
ValidatorUpdates: abci.Validators{valSet},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -18,8 +18,8 @@ func (tx kvstoreTx) Type() string {
|
||||||
return "kvstore"
|
return "kvstore"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx kvstoreTx) GetMsg() sdk.Msg {
|
func (tx kvstoreTx) GetMsgs() []sdk.Msg {
|
||||||
return tx
|
return []sdk.Msg{tx}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx kvstoreTx) GetMemo() string {
|
func (tx kvstoreTx) GetMemo() string {
|
||||||
|
|
|
@ -31,8 +31,8 @@ func (tx kvstoreTx) Type() string {
|
||||||
return "kvstore"
|
return "kvstore"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx kvstoreTx) GetMsg() sdk.Msg {
|
func (tx kvstoreTx) GetMsgs() []sdk.Msg {
|
||||||
return tx
|
return []sdk.Msg{tx}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx kvstoreTx) GetMemo() string {
|
func (tx kvstoreTx) GetMemo() string {
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
|
||||||
abci "github.com/tendermint/abci/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Result is the union of ResponseDeliverTx and ResponseCheckTx.
|
// Result is the union of ResponseDeliverTx and ResponseCheckTx.
|
||||||
type Result struct {
|
type Result struct {
|
||||||
|
|
||||||
|
@ -26,9 +22,6 @@ type Result struct {
|
||||||
FeeAmount int64
|
FeeAmount int64
|
||||||
FeeDenom string
|
FeeDenom string
|
||||||
|
|
||||||
// Changes to the validator set.
|
|
||||||
ValidatorUpdates []abci.Validator
|
|
||||||
|
|
||||||
// Tags are used for transaction indexing and pubsub.
|
// Tags are used for transaction indexing and pubsub.
|
||||||
Tags Tags
|
Tags Tags
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ type Msg interface {
|
||||||
type Tx interface {
|
type Tx interface {
|
||||||
|
|
||||||
// Gets the Msg.
|
// Gets the Msg.
|
||||||
GetMsg() Msg
|
GetMsgs() []Msg
|
||||||
|
|
||||||
// Gets the memo.
|
// Gets the memo.
|
||||||
GetMemo() string
|
GetMemo() string
|
||||||
|
|
|
@ -52,10 +52,10 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
// charge gas for the memo
|
// charge gas for the memo
|
||||||
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(memo)), "memo")
|
ctx.GasMeter().ConsumeGas(memoCostPerByte*sdk.Gas(len(memo)), "memo")
|
||||||
|
|
||||||
msg := tx.GetMsg()
|
msgs := tx.GetMsgs()
|
||||||
|
|
||||||
// Assert that number of signatures is correct.
|
// Assert that number of signatures is correct.
|
||||||
var signerAddrs = msg.GetSigners()
|
var signerAddrs = stdTx.GetSigners()
|
||||||
if len(sigs) != len(signerAddrs) {
|
if len(sigs) != len(signerAddrs) {
|
||||||
return ctx,
|
return ctx,
|
||||||
sdk.ErrUnauthorized("wrong number of signers").Result(),
|
sdk.ErrUnauthorized("wrong number of signers").Result(),
|
||||||
|
@ -78,7 +78,6 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
if chainID == "" {
|
if chainID == "" {
|
||||||
chainID = viper.GetString("chain-id")
|
chainID = viper.GetString("chain-id")
|
||||||
}
|
}
|
||||||
signBytes := StdSignBytes(ctx.ChainID(), accNums, sequences, fee, msg, memo)
|
|
||||||
|
|
||||||
// Check sig and nonce and collect signer accounts.
|
// Check sig and nonce and collect signer accounts.
|
||||||
var signerAccs = make([]Account, len(signerAddrs))
|
var signerAccs = make([]Account, len(signerAddrs))
|
||||||
|
@ -86,6 +85,7 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler {
|
||||||
signerAddr, sig := signerAddrs[i], sigs[i]
|
signerAddr, sig := signerAddrs[i], sigs[i]
|
||||||
|
|
||||||
// check signature, return account with incremented nonce
|
// check signature, return account with incremented nonce
|
||||||
|
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], sequences[i], fee, msgs, tx.GetMemo())
|
||||||
signerAcc, res := processSig(
|
signerAcc, res := processSig(
|
||||||
ctx, am,
|
ctx, am,
|
||||||
signerAddr, sig, signBytes,
|
signerAddr, sig, signBytes,
|
||||||
|
|
|
@ -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))
|
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 {
|
func newTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee) sdk.Tx {
|
||||||
signBytes := StdSignBytes(ctx.ChainID(), accNums, seqs, fee, msg, "")
|
sigs := make([]StdSignature, len(privs))
|
||||||
return newTestTxWithSignBytes(msg, privs, accNums, seqs, fee, signBytes, "")
|
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 {
|
func newTestTxWithMemo(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []int64, seqs []int64, fee StdFee, memo string) sdk.Tx {
|
||||||
signBytes := StdSignBytes(ctx.ChainID(), accNums, seqs, fee, msg, memo)
|
sigs := make([]StdSignature, len(privs))
|
||||||
return newTestTxWithSignBytes(msg, privs, accNums, seqs, fee, signBytes, memo)
|
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))
|
sigs := make([]StdSignature, len(privs))
|
||||||
for i, priv := range privs {
|
for i, priv := range privs {
|
||||||
sigs[i] = StdSignature{PubKey: priv.PubKey(), Signature: priv.Sign(signBytes), AccountNumber: accNums[i], Sequence: seqs[i]}
|
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
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,25 +109,36 @@ func TestAnteHandlerSigErrors(t *testing.T) {
|
||||||
// keys and addresses
|
// keys and addresses
|
||||||
priv1, addr1 := privAndAddr()
|
priv1, addr1 := privAndAddr()
|
||||||
priv2, addr2 := privAndAddr()
|
priv2, addr2 := privAndAddr()
|
||||||
|
priv3, addr3 := privAndAddr()
|
||||||
|
|
||||||
// msg and signatures
|
// msg and signatures
|
||||||
var tx sdk.Tx
|
var tx sdk.Tx
|
||||||
msg := newTestMsg(addr1, addr2)
|
msg1 := newTestMsg(addr1, addr2)
|
||||||
|
msg2 := newTestMsg(addr1, addr3)
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
|
|
||||||
|
msgs := []sdk.Msg{msg1, msg2}
|
||||||
|
|
||||||
// test no signatures
|
// test no signatures
|
||||||
privs, accNums, seqs := []crypto.PrivKey{}, []int64{}, []int64{}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
|
||||||
|
|
||||||
// test num sigs dont match GetSigners
|
// test num sigs dont match GetSigners
|
||||||
privs, accNums, seqs = []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
|
||||||
|
|
||||||
// test an unrecognized account
|
// test an unrecognized account
|
||||||
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{0, 0}
|
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2, priv3}, []int64{0, 1, 2}, []int64{0, 0, 0}
|
||||||
tx = newTestTx(ctx, msg, privs, accNums, seqs, fee)
|
tx = newTestTx(ctx, msgs, privs, accNums, seqs, fee)
|
||||||
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnknownAddress)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnknownAddress)
|
||||||
|
|
||||||
// save the first account, but second is still unrecognized
|
// save the first account, but second is still unrecognized
|
||||||
|
@ -154,30 +176,34 @@ func TestAnteHandlerAccountNumbers(t *testing.T) {
|
||||||
msg := newTestMsg(addr1)
|
msg := newTestMsg(addr1)
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
|
|
||||||
|
msgs := []sdk.Msg{msg}
|
||||||
|
|
||||||
// test good tx from one signer
|
// test good tx from one signer
|
||||||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// new tx from wrong account number
|
// new tx from wrong account number
|
||||||
seqs = []int64{1}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
|
||||||
|
|
||||||
// from correct account number
|
// from correct account number
|
||||||
seqs = []int64{1}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// new tx with another signer and incorrect account numbers
|
// 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}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
|
||||||
|
|
||||||
// correct account numbers
|
// correct account numbers
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{2, 0}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +221,7 @@ func TestAnteHandlerSequences(t *testing.T) {
|
||||||
// keys and addresses
|
// keys and addresses
|
||||||
priv1, addr1 := privAndAddr()
|
priv1, addr1 := privAndAddr()
|
||||||
priv2, addr2 := privAndAddr()
|
priv2, addr2 := privAndAddr()
|
||||||
|
priv3, addr3 := privAndAddr()
|
||||||
|
|
||||||
// set the accounts
|
// set the accounts
|
||||||
acc1 := mapper.NewAccountWithAddress(ctx, addr1)
|
acc1 := mapper.NewAccountWithAddress(ctx, addr1)
|
||||||
|
@ -203,15 +230,20 @@ func TestAnteHandlerSequences(t *testing.T) {
|
||||||
acc2 := mapper.NewAccountWithAddress(ctx, addr2)
|
acc2 := mapper.NewAccountWithAddress(ctx, addr2)
|
||||||
acc2.SetCoins(newCoins())
|
acc2.SetCoins(newCoins())
|
||||||
mapper.SetAccount(ctx, acc2)
|
mapper.SetAccount(ctx, acc2)
|
||||||
|
acc3 := mapper.NewAccountWithAddress(ctx, addr3)
|
||||||
|
acc3.SetCoins(newCoins())
|
||||||
|
mapper.SetAccount(ctx, acc3)
|
||||||
|
|
||||||
// msg and signatures
|
// msg and signatures
|
||||||
var tx sdk.Tx
|
var tx sdk.Tx
|
||||||
msg := newTestMsg(addr1)
|
msg := newTestMsg(addr1)
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
|
|
||||||
|
msgs := []sdk.Msg{msg}
|
||||||
|
|
||||||
// test good tx from one signer
|
// test good tx from one signer
|
||||||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// test sending it again fails (replay protection)
|
// test sending it again fails (replay protection)
|
||||||
|
@ -219,13 +251,16 @@ func TestAnteHandlerSequences(t *testing.T) {
|
||||||
|
|
||||||
// fix sequence, should pass
|
// fix sequence, should pass
|
||||||
seqs = []int64{1}
|
seqs = []int64{1}
|
||||||
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
|
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
|
||||||
checkValidTx(t, anteHandler, ctx, tx)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// new tx with another signer and correct sequences
|
// new tx with another signer and correct sequences
|
||||||
msg = newTestMsg(addr1, addr2)
|
msg1 := newTestMsg(addr1, addr2)
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{2, 0}
|
msg2 := newTestMsg(addr3, addr1)
|
||||||
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// replay fails
|
// replay fails
|
||||||
|
@ -233,18 +268,20 @@ func TestAnteHandlerSequences(t *testing.T) {
|
||||||
|
|
||||||
// tx from just second signer with incorrect sequence fails
|
// tx from just second signer with incorrect sequence fails
|
||||||
msg = newTestMsg(addr2)
|
msg = newTestMsg(addr2)
|
||||||
|
msgs = []sdk.Msg{msg}
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{1}, []int64{0}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidSequence)
|
||||||
|
|
||||||
// fix the sequence and it passes
|
// 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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
// another tx from both of them that passes
|
// another tx from both of them that passes
|
||||||
msg = newTestMsg(addr1, addr2)
|
msg = newTestMsg(addr1, addr2)
|
||||||
|
msgs = []sdk.Msg{msg}
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv1, priv2}, []int64{0, 1}, []int64{3, 2}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,9 +308,10 @@ func TestAnteHandlerFees(t *testing.T) {
|
||||||
msg := newTestMsg(addr1)
|
msg := newTestMsg(addr1)
|
||||||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
|
msgs := []sdk.Msg{msg}
|
||||||
|
|
||||||
// signer does not have enough funds to pay the fee
|
// 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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInsufficientFunds)
|
||||||
|
|
||||||
acc1.SetCoins(sdk.Coins{sdk.NewCoin("atom", 149)})
|
acc1.SetCoins(sdk.Coins{sdk.NewCoin("atom", 149)})
|
||||||
|
@ -314,22 +352,73 @@ func TestAnteHandlerMemoGas(t *testing.T) {
|
||||||
fee := NewStdFee(0, sdk.NewCoin("atom", 0))
|
fee := NewStdFee(0, sdk.NewCoin("atom", 0))
|
||||||
|
|
||||||
// tx does not have enough gas
|
// 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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas)
|
||||||
|
|
||||||
// tx with memo doesn't have enough gas
|
// tx with memo doesn't have enough gas
|
||||||
fee = NewStdFee(1001, sdk.NewCoin("atom", 0))
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeOutOfGas)
|
||||||
|
|
||||||
// memo too large
|
// memo too large
|
||||||
fee = NewStdFee(2001, sdk.NewCoin("atom", 0))
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeMemoTooLarge)
|
||||||
|
|
||||||
// tx with memo has enough gas
|
// tx with memo has enough gas
|
||||||
fee = NewStdFee(1100, sdk.NewCoin("atom", 0))
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +446,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
|
||||||
|
|
||||||
var tx sdk.Tx
|
var tx sdk.Tx
|
||||||
msg := newTestMsg(addr1)
|
msg := newTestMsg(addr1)
|
||||||
|
msgs := []sdk.Msg{msg}
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
fee2 := newStdFee()
|
fee2 := newStdFee()
|
||||||
fee2.Gas += 100
|
fee2.Gas += 100
|
||||||
|
@ -365,7 +455,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
|
||||||
|
|
||||||
// test good tx and signBytes
|
// test good tx and signBytes
|
||||||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
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)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
chainID := ctx.ChainID()
|
chainID := ctx.ChainID()
|
||||||
|
@ -374,26 +464,26 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
chainID string
|
chainID string
|
||||||
accnums []int64
|
accnum int64
|
||||||
seqs []int64
|
seq int64
|
||||||
fee StdFee
|
fee StdFee
|
||||||
msg sdk.Msg
|
msgs []sdk.Msg
|
||||||
code sdk.CodeType
|
code sdk.CodeType
|
||||||
}{
|
}{
|
||||||
{chainID2, []int64{0}, []int64{1}, fee, msg, codeUnauth}, // test wrong chain_id
|
{chainID2, 0, 1, fee, msgs, codeUnauth}, // test wrong chain_id
|
||||||
{chainID, []int64{0}, []int64{2}, fee, msg, codeUnauth}, // test wrong seqs
|
{chainID, 0, 2, fee, msgs, codeUnauth}, // test wrong seqs
|
||||||
{chainID, []int64{0}, []int64{1, 2}, fee, msg, codeUnauth}, // test wrong seqs
|
{chainID, 1, 1, fee, msgs, codeUnauth}, // test wrong accnum
|
||||||
{chainID, []int64{1}, []int64{1}, fee, msg, codeUnauth}, // test wrong accnum
|
{chainID, 0, 1, fee, []sdk.Msg{newTestMsg(addr2)}, codeUnauth}, // test wrong msg
|
||||||
{chainID, []int64{0}, []int64{1}, fee, newTestMsg(addr2), codeUnauth}, // test wrong msg
|
{chainID, 0, 1, fee2, msgs, codeUnauth}, // test wrong fee
|
||||||
{chainID, []int64{0}, []int64{1}, fee2, msg, codeUnauth}, // test wrong fee
|
{chainID, 0, 1, fee3, msgs, codeUnauth}, // test wrong fee
|
||||||
{chainID, []int64{0}, []int64{1}, fee3, msg, codeUnauth}, // test wrong fee
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privs, seqs = []crypto.PrivKey{priv1}, []int64{1}
|
privs, seqs = []crypto.PrivKey{priv1}, []int64{1}
|
||||||
for _, cs := range cases {
|
for _, cs := range cases {
|
||||||
tx := newTestTxWithSignBytes(
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, cs.code)
|
||||||
|
@ -401,13 +491,14 @@ func TestAnteHandlerBadSignBytes(t *testing.T) {
|
||||||
|
|
||||||
// test wrong signer if public key exist
|
// test wrong signer if public key exist
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv2}, []int64{0}, []int64{1}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeUnauthorized)
|
||||||
|
|
||||||
// test wrong signer if public doesn't exist
|
// test wrong signer if public doesn't exist
|
||||||
msg = newTestMsg(addr2)
|
msg = newTestMsg(addr2)
|
||||||
|
msgs = []sdk.Msg{msg}
|
||||||
privs, accnums, seqs = []crypto.PrivKey{priv1}, []int64{1}, []int64{0}
|
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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -438,9 +529,10 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
|
||||||
|
|
||||||
// test good tx and set public key
|
// test good tx and set public key
|
||||||
msg := newTestMsg(addr1)
|
msg := newTestMsg(addr1)
|
||||||
|
msgs := []sdk.Msg{msg}
|
||||||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0}
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
tx = newTestTx(ctx, msg, privs, accnums, seqs, fee)
|
tx = newTestTx(ctx, msgs, privs, accnums, seqs, fee)
|
||||||
checkValidTx(t, anteHandler, ctx, tx)
|
checkValidTx(t, anteHandler, ctx, tx)
|
||||||
|
|
||||||
acc1 = mapper.GetAccount(ctx, addr1)
|
acc1 = mapper.GetAccount(ctx, addr1)
|
||||||
|
@ -448,7 +540,8 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
|
||||||
|
|
||||||
// test public key not found
|
// test public key not found
|
||||||
msg = newTestMsg(addr2)
|
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 := tx.(StdTx).GetSignatures()
|
||||||
sigs[0].PubKey = nil
|
sigs[0].PubKey = nil
|
||||||
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
|
||||||
|
@ -457,7 +550,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) {
|
||||||
assert.Nil(t, acc2.GetPubKey())
|
assert.Nil(t, acc2.GetPubKey())
|
||||||
|
|
||||||
// test invalid signature and public key
|
// 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)
|
checkInvalidTx(t, anteHandler, ctx, tx, sdk.CodeInvalidPubKey)
|
||||||
|
|
||||||
acc2 = mapper.GetAccount(ctx, addr2)
|
acc2 = mapper.GetAccount(ctx, addr2)
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestMsgChangePubKey(t *testing.T) {
|
||||||
assert.Equal(t, acc1, res1.(*auth.BaseAccount))
|
assert.Equal(t, acc1, res1.(*auth.BaseAccount))
|
||||||
|
|
||||||
// Run a CheckDeliver
|
// 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
|
// Check balances
|
||||||
CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 67)})
|
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)
|
acc2 := mapp.AccountMapper.GetAccount(ctxDeliver, addr1)
|
||||||
|
|
||||||
// send a MsgChangePubKey
|
// 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)
|
acc2 = mapp.AccountMapper.GetAccount(ctxDeliver, addr1)
|
||||||
|
|
||||||
assert.True(t, priv2.PubKey().Equals(acc2.GetPubKey()))
|
assert.True(t, priv2.PubKey().Equals(acc2.GetPubKey()))
|
||||||
|
|
||||||
// signing a SendMsg with the old privKey should be an auth error
|
// signing a SendMsg with the old privKey should be an auth error
|
||||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
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)
|
res := mapp.Deliver(tx)
|
||||||
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||||
|
|
||||||
// resigning the tx with the new correct priv key should work
|
// 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
|
// Check balances
|
||||||
CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
|
CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
|
||||||
|
|
|
@ -33,7 +33,7 @@ func CheckBalance(t *testing.T, app *App, addr sdk.Address, exp sdk.Coins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a signed transaction
|
// 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
|
// make the transaction free
|
||||||
fee := auth.StdFee{
|
fee := auth.StdFee{
|
||||||
|
@ -46,26 +46,26 @@ func GenTx(msg sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25
|
||||||
for i, p := range priv {
|
for i, p := range priv {
|
||||||
sigs[i] = auth.StdSignature{
|
sigs[i] = auth.StdSignature{
|
||||||
PubKey: p.PubKey(),
|
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],
|
AccountNumber: accnums[i],
|
||||||
Sequence: seq[i],
|
Sequence: seq[i],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return auth.NewStdTx(msg, fee, sigs, memo)
|
return auth.NewStdTx(msgs, fee, sigs, memo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check a transaction result
|
// check a transaction result
|
||||||
func SignCheck(t *testing.T, app *baseapp.BaseApp, msg sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result {
|
func SignCheck(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result {
|
||||||
tx := GenTx(msg, accnums, seq, priv...)
|
tx := GenTx(msgs, accnums, seq, priv...)
|
||||||
res := app.Check(tx)
|
res := app.Check(tx)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulate a block
|
// 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
|
// Sign the tx
|
||||||
tx := GenTx(msg, accnums, seq, priv...)
|
tx := GenTx(msgs, accnums, seq, priv...)
|
||||||
|
|
||||||
// Run a Check
|
// Run a Check
|
||||||
res := app.Check(tx)
|
res := app.Check(tx)
|
||||||
|
|
|
@ -12,15 +12,15 @@ var _ sdk.Tx = (*StdTx)(nil)
|
||||||
// StdTx is a standard way to wrap a Msg with Fee and Signatures.
|
// 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).
|
// NOTE: the first signature is the FeePayer (Signatures must not be nil).
|
||||||
type StdTx struct {
|
type StdTx struct {
|
||||||
Msg sdk.Msg `json:"msg"`
|
Msgs []sdk.Msg `json:"msg"`
|
||||||
Fee StdFee `json:"fee"`
|
Fee StdFee `json:"fee"`
|
||||||
Signatures []StdSignature `json:"signatures"`
|
Signatures []StdSignature `json:"signatures"`
|
||||||
Memo string `json:"memo"`
|
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{
|
return StdTx{
|
||||||
Msg: msg,
|
Msgs: msgs,
|
||||||
Fee: fee,
|
Fee: fee,
|
||||||
Signatures: sigs,
|
Signatures: sigs,
|
||||||
Memo: memo,
|
Memo: memo,
|
||||||
|
@ -28,12 +28,32 @@ func NewStdTx(msg sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx {
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint
|
//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
|
//nolint
|
||||||
func (tx StdTx) GetMemo() string { return tx.Memo }
|
func (tx StdTx) GetMemo() string { return tx.Memo }
|
||||||
|
|
||||||
// Signatures returns the signature of signers who signed the Msg.
|
// 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
|
// CONTRACT: Length returned is same as length of
|
||||||
// pubkeys returned from MsgKeySigners, and the order
|
// pubkeys returned from MsgKeySigners, and the order
|
||||||
// matches.
|
// 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().
|
// for the transactions. It's the first address returned by msg.GetSigners().
|
||||||
// If GetSigners() is empty, this panics.
|
// If GetSigners() is empty, this panics.
|
||||||
func FeePayer(tx sdk.Tx) sdk.Address {
|
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
|
// and the Sequence numbers for each signature (prevent
|
||||||
// inchain replay and enforce tx ordering per account).
|
// inchain replay and enforce tx ordering per account).
|
||||||
type StdSignDoc struct {
|
type StdSignDoc struct {
|
||||||
ChainID string `json:"chain_id"`
|
ChainID string `json:"chain_id"`
|
||||||
AccountNumbers []int64 `json:"account_numbers"`
|
AccountNumber int64 `json:"account_number"`
|
||||||
Sequences []int64 `json:"sequences"`
|
Sequence int64 `json:"sequence"`
|
||||||
Fee json.RawMessage `json:"fee"`
|
FeeBytes []byte `json:"fee_bytes"`
|
||||||
Msg json.RawMessage `json:"msg"`
|
MsgsBytes []byte `json:"msg_bytes"`
|
||||||
Memo string `json:"memo"`
|
Memo string `json:"memo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdSignBytes returns the bytes to sign for a transaction.
|
// StdSignBytes returns the bytes to sign for a transaction.
|
||||||
// TODO: change the API to just take a chainID and StdTx ?
|
// 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{
|
bz, err := json.Marshal(StdSignDoc{
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
AccountNumbers: accnums,
|
AccountNumber: accnum,
|
||||||
Sequences: sequences,
|
Sequence: sequence,
|
||||||
Fee: json.RawMessage(fee.Bytes()),
|
FeeBytes: fee.Bytes(),
|
||||||
Msg: json.RawMessage(msg.GetSignBytes()),
|
MsgsBytes: msgBytes,
|
||||||
Memo: memo,
|
Memo: memo,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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
|
// a Msg with the other requirements for a StdSignDoc before
|
||||||
// it is signed. For use in the CLI.
|
// it is signed. For use in the CLI.
|
||||||
type StdSignMsg struct {
|
type StdSignMsg struct {
|
||||||
ChainID string
|
ChainID string
|
||||||
AccountNumbers []int64
|
AccountNumber int64
|
||||||
Sequences []int64
|
Sequence int64
|
||||||
Fee StdFee
|
Fee StdFee
|
||||||
Msg sdk.Msg
|
Msgs []sdk.Msg
|
||||||
Memo string
|
Memo string
|
||||||
}
|
}
|
||||||
|
|
||||||
// get message bytes
|
// get message bytes
|
||||||
func (msg StdSignMsg) Bytes() []byte {
|
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
|
// Standard Signature
|
||||||
|
|
|
@ -19,12 +19,12 @@ import (
|
||||||
func TestStdTx(t *testing.T) {
|
func TestStdTx(t *testing.T) {
|
||||||
priv := crypto.GenPrivKeyEd25519()
|
priv := crypto.GenPrivKeyEd25519()
|
||||||
addr := priv.PubKey().Address()
|
addr := priv.PubKey().Address()
|
||||||
msg := sdk.NewTestMsg(addr)
|
msgs := []sdk.Msg{sdk.NewTestMsg(addr)}
|
||||||
fee := newStdFee()
|
fee := newStdFee()
|
||||||
sigs := []StdSignature{}
|
sigs := []StdSignature{}
|
||||||
|
|
||||||
tx := NewStdTx(msg, fee, sigs, "")
|
tx := NewStdTx(msgs, fee, sigs, "")
|
||||||
assert.Equal(t, msg, tx.GetMsg())
|
assert.Equal(t, msgs, tx.GetMsgs())
|
||||||
assert.Equal(t, sigs, tx.GetSignatures())
|
assert.Equal(t, sigs, tx.GetSignatures())
|
||||||
|
|
||||||
feePayer := FeePayer(tx)
|
feePayer := FeePayer(tx)
|
||||||
|
|
|
@ -107,25 +107,25 @@ func TestMsgSendWithAccounts(t *testing.T) {
|
||||||
assert.Equal(t, acc, res1.(*auth.BaseAccount))
|
assert.Equal(t, acc, res1.(*auth.BaseAccount))
|
||||||
|
|
||||||
// Run a CheckDeliver
|
// 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
|
// Check balances
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)})
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
||||||
|
|
||||||
// Delivering again should cause replay error
|
// 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
|
// bumping the txnonce number without resigning should be an auth error
|
||||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
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
|
tx.Signatures[0].Sequence = 1
|
||||||
res := mapp.Deliver(tx)
|
res := mapp.Deliver(tx)
|
||||||
|
|
||||||
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||||
|
|
||||||
// resigning the tx with the bumped sequence should work
|
// 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) {
|
func TestMsgSendMultipleOut(t *testing.T) {
|
||||||
|
@ -145,7 +145,7 @@ func TestMsgSendMultipleOut(t *testing.T) {
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, accs)
|
||||||
|
|
||||||
// Simulate a Block
|
// 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
|
// Check balances
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
||||||
|
@ -173,7 +173,7 @@ func TestSengMsgMultipleInOut(t *testing.T) {
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, accs)
|
||||||
|
|
||||||
// CheckDeliver
|
// 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
|
// Check balances
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
||||||
|
@ -194,14 +194,14 @@ func TestMsgSendDependent(t *testing.T) {
|
||||||
mock.SetGenesis(mapp, accs)
|
mock.SetGenesis(mapp, accs)
|
||||||
|
|
||||||
// CheckDeliver
|
// 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
|
// Check balances
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)})
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
mock.CheckBalance(t, mapp, addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)})
|
||||||
|
|
||||||
// Simulate a Block
|
// 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
|
// Check balances
|
||||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)})
|
||||||
|
|
|
@ -47,7 +47,7 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command {
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// build and sign the transaction, then broadcast to Tendermint
|
||||||
msg := client.BuildMsg(from, to, coins)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreCont
|
||||||
// sign
|
// sign
|
||||||
ctx = ctx.WithAccountNumber(m.AccountNumber)
|
ctx = ctx.WithAccountNumber(m.AccountNumber)
|
||||||
ctx = ctx.WithSequence(m.Sequence)
|
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 {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte(err.Error()))
|
w.Write([]byte(err.Error()))
|
||||||
|
|
|
@ -71,10 +71,10 @@ func TestIBCMsgs(t *testing.T) {
|
||||||
Sequence: 0,
|
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.CheckBalance(t, mapp, addr1, emptyCoins)
|
||||||
mock.SignCheckDeliver(t, mapp.BaseApp, transferMsg, []int64{0}, []int64{1}, false, priv1)
|
mock.SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{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{receiveMsg}, []int64{0}, []int64{2}, true, priv1)
|
||||||
mock.CheckBalance(t, mapp, addr1, coins)
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func IBCTransferCmd(cdc *wire.Codec) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get password
|
// get password
|
||||||
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, msg, cdc)
|
res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ func (c relayCommander) refine(bz []byte, sequence int64, passphrase string) []b
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.NewCoreContextFromViper().WithSequence(sequence)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.Core
|
||||||
// sign
|
// sign
|
||||||
ctx = ctx.WithAccountNumber(m.AccountNumber)
|
ctx = ctx.WithAccountNumber(m.AccountNumber)
|
||||||
ctx = ctx.WithSequence(m.Sequence)
|
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 {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte(err.Error()))
|
w.Write([]byte(err.Error()))
|
||||||
|
|
|
@ -92,7 +92,7 @@ func TestSlashingMsgs(t *testing.T) {
|
||||||
createValidatorMsg := stake.NewMsgCreateValidator(
|
createValidatorMsg := stake.NewMsgCreateValidator(
|
||||||
addr1, priv1.PubKey(), bondCoin, description,
|
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)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
mapp.BeginBlock(abci.RequestBeginBlock{})
|
||||||
|
|
||||||
|
@ -106,6 +106,6 @@ func TestSlashingMsgs(t *testing.T) {
|
||||||
checkValidatorSigningInfo(t, mapp, keeper, addr1, false)
|
checkValidatorSigningInfo(t, mapp, keeper, addr1, false)
|
||||||
|
|
||||||
// unrevoke should fail with unknown validator
|
// 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)
|
require.Equal(t, sdk.ToABCICode(DefaultCodespace, CodeInvalidValidator), res.Code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func GetCmdUnrevoke(cdc *wire.Codec) *cobra.Command {
|
||||||
msg := slashing.NewMsgUnrevoke(validatorAddr)
|
msg := slashing.NewMsgUnrevoke(validatorAddr)
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
createValidatorMsg := NewMsgCreateValidator(
|
createValidatorMsg := NewMsgCreateValidator(
|
||||||
addr1, priv1.PubKey(), bondCoin, description,
|
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)})
|
mock.CheckBalance(t, mapp, addr1, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
mapp.BeginBlock(abci.RequestBeginBlock{})
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
|
|
||||||
description = NewDescription("bar_moniker", "", "", "")
|
description = NewDescription("bar_moniker", "", "", "")
|
||||||
editValidatorMsg := NewMsgEditValidator(addr1, description)
|
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)
|
validator = checkValidator(t, mapp, keeper, addr1, true)
|
||||||
require.Equal(t, description, validator.Description)
|
require.Equal(t, description, validator.Description)
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
|
|
||||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin})
|
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin})
|
||||||
delegateMsg := NewMsgDelegate(addr2, addr1, bondCoin)
|
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)})
|
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin.Minus(bondCoin)})
|
||||||
checkDelegation(t, mapp, keeper, addr2, addr1, true, sdk.NewRat(10))
|
checkDelegation(t, mapp, keeper, addr2, addr1, true, sdk.NewRat(10))
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ func TestStakeMsgs(t *testing.T) {
|
||||||
// Unbond
|
// Unbond
|
||||||
|
|
||||||
unbondMsg := NewMsgUnbond(addr2, addr1, "MAX")
|
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})
|
mock.CheckBalance(t, mapp, addr2, sdk.Coins{genCoin})
|
||||||
checkDelegation(t, mapp, keeper, addr2, addr1, false, sdk.Rat{})
|
checkDelegation(t, mapp, keeper, addr2, addr1, false, sdk.Rat{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ func GetCmdCreateValidator(cdc *wire.Codec) *cobra.Command {
|
||||||
msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description)
|
msg := stake.NewMsgCreateValidator(validatorAddr, pk, amount, description)
|
||||||
|
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ func GetCmdEditValidator(cdc *wire.Codec) *cobra.Command {
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// build and sign the transaction, then broadcast to Tendermint
|
||||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ func GetCmdDelegate(cdc *wire.Codec) *cobra.Command {
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// build and sign the transaction, then broadcast to Tendermint
|
||||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ func GetCmdUnbond(cdc *wire.Codec) *cobra.Command {
|
||||||
// build and sign the transaction, then broadcast to Tendermint
|
// build and sign the transaction, then broadcast to Tendermint
|
||||||
ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(cdc))
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx conte
|
||||||
ctx = ctx.WithSequence(m.Sequence)
|
ctx = ctx.WithSequence(m.Sequence)
|
||||||
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 {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte(err.Error()))
|
w.Write([]byte(err.Error()))
|
||||||
|
|
Loading…
Reference in New Issue