github.com/Finschia/finschia-sdk@v0.48.1/x/bank/app_test.go (about) 1 package bank_test 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 8 9 "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" 10 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 11 "github.com/Finschia/finschia-sdk/simapp" 12 sdk "github.com/Finschia/finschia-sdk/types" 13 authtypes "github.com/Finschia/finschia-sdk/x/auth/types" 14 "github.com/Finschia/finschia-sdk/x/bank/types" 15 ) 16 17 type ( 18 expectedBalance struct { 19 addr sdk.AccAddress 20 coins sdk.Coins 21 } 22 23 appTestCase struct { 24 desc string 25 expSimPass bool 26 expPass bool 27 msgs []sdk.Msg 28 accNums []uint64 29 accSeqs []uint64 30 privKeys []cryptotypes.PrivKey 31 expectedBalances []expectedBalance 32 } 33 ) 34 35 var ( 36 priv1 = secp256k1.GenPrivKey() 37 addr1 = sdk.AccAddress(priv1.PubKey().Address()) 38 priv2 = secp256k1.GenPrivKey() 39 addr2 = sdk.AccAddress(priv2.PubKey().Address()) 40 addr3 = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) 41 priv4 = secp256k1.GenPrivKey() 42 addr4 = sdk.AccAddress(priv4.PubKey().Address()) 43 44 coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} 45 halfCoins = sdk.Coins{sdk.NewInt64Coin("foocoin", 5)} 46 47 sendMsg1 = types.NewMsgSend(addr1, addr2, coins) 48 49 multiSendMsg1 = &types.MsgMultiSend{ 50 Inputs: []types.Input{types.NewInput(addr1, coins)}, 51 Outputs: []types.Output{types.NewOutput(addr2, coins)}, 52 } 53 multiSendMsg2 = &types.MsgMultiSend{ 54 Inputs: []types.Input{types.NewInput(addr1, coins)}, 55 Outputs: []types.Output{ 56 types.NewOutput(addr2, halfCoins), 57 types.NewOutput(addr3, halfCoins), 58 }, 59 } 60 multiSendMsg3 = &types.MsgMultiSend{ 61 Inputs: []types.Input{ 62 types.NewInput(addr1, coins), 63 types.NewInput(addr4, coins), 64 }, 65 Outputs: []types.Output{ 66 types.NewOutput(addr2, coins), 67 types.NewOutput(addr3, coins), 68 }, 69 } 70 multiSendMsg4 = &types.MsgMultiSend{ 71 Inputs: []types.Input{ 72 types.NewInput(addr2, coins), 73 }, 74 Outputs: []types.Output{ 75 types.NewOutput(addr1, coins), 76 }, 77 } 78 multiSendMsg5 = &types.MsgMultiSend{ 79 Inputs: []types.Input{ 80 types.NewInput(addr1, coins), 81 }, 82 Outputs: []types.Output{ 83 types.NewOutput(moduleAccAddr, coins), 84 }, 85 } 86 ) 87 88 func TestSendNotEnoughBalance(t *testing.T) { 89 acc := &authtypes.BaseAccount{ 90 Address: addr1.String(), 91 } 92 93 genAccs := []authtypes.GenesisAccount{acc} 94 app := simapp.SetupWithGenesisAccounts(genAccs) 95 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 96 97 require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) 98 99 app.Commit() 100 101 res1 := app.AccountKeeper.GetAccount(ctx, addr1) 102 require.NotNil(t, res1) 103 require.Equal(t, acc, res1.(*authtypes.BaseAccount)) 104 105 origAccNum := res1.GetAccountNumber() 106 origSeq := res1.GetSequence() 107 108 sendMsg := types.NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 100)}) 109 header := tmproto.Header{Height: app.LastBlockHeight() + 1} 110 txGen := simapp.MakeTestEncodingConfig().TxConfig 111 _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{sendMsg}, "", []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1) 112 require.Error(t, err) 113 114 simapp.CheckBalance(t, app, addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 67)}) 115 116 res2 := app.AccountKeeper.GetAccount(app.NewContext(true, tmproto.Header{}), addr1) 117 require.NotNil(t, res2) 118 119 require.Equal(t, res2.GetAccountNumber(), origAccNum) 120 require.Equal(t, res2.GetSequence(), origSeq+1) 121 } 122 123 func TestMsgMultiSendWithAccounts(t *testing.T) { 124 acc := &authtypes.BaseAccount{ 125 Address: addr1.String(), 126 } 127 128 genAccs := []authtypes.GenesisAccount{acc} 129 app := simapp.SetupWithGenesisAccounts(genAccs) 130 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 131 132 require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))) 133 134 app.Commit() 135 136 res1 := app.AccountKeeper.GetAccount(ctx, addr1) 137 require.NotNil(t, res1) 138 require.Equal(t, acc, res1.(*authtypes.BaseAccount)) 139 140 testCases := []appTestCase{ 141 { 142 desc: "make a valid tx", 143 msgs: []sdk.Msg{multiSendMsg1}, 144 accNums: []uint64{0}, 145 accSeqs: []uint64{0}, 146 expSimPass: true, 147 expPass: true, 148 privKeys: []cryptotypes.PrivKey{priv1}, 149 expectedBalances: []expectedBalance{ 150 {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 57)}}, 151 {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, 152 }, 153 }, 154 { 155 desc: "wrong accNum should pass Simulate, but not Deliver", 156 msgs: []sdk.Msg{multiSendMsg1, multiSendMsg2}, 157 accNums: []uint64{1}, // wrong account number 158 accSeqs: []uint64{1}, 159 expSimPass: true, // doesn't check signature 160 expPass: false, 161 privKeys: []cryptotypes.PrivKey{priv1}, 162 }, 163 { 164 desc: "wrong accSeq should not pass Simulate", 165 msgs: []sdk.Msg{multiSendMsg5}, 166 accNums: []uint64{0}, 167 accSeqs: []uint64{0}, // wrong account sequence 168 expSimPass: false, 169 expPass: false, 170 privKeys: []cryptotypes.PrivKey{priv1}, 171 }, 172 } 173 174 for _, tc := range testCases { 175 header := tmproto.Header{Height: app.LastBlockHeight() + 1} 176 txGen := simapp.MakeTestEncodingConfig().TxConfig 177 _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...) 178 if tc.expPass { 179 require.NoError(t, err) 180 } else { 181 require.Error(t, err) 182 } 183 184 for _, eb := range tc.expectedBalances { 185 simapp.CheckBalance(t, app, eb.addr, eb.coins) 186 } 187 } 188 } 189 190 func TestMsgMultiSendMultipleOut(t *testing.T) { 191 acc1 := &authtypes.BaseAccount{ 192 Address: addr1.String(), 193 } 194 acc2 := &authtypes.BaseAccount{ 195 Address: addr2.String(), 196 } 197 198 genAccs := []authtypes.GenesisAccount{acc1, acc2} 199 app := simapp.SetupWithGenesisAccounts(genAccs) 200 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 201 202 require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 203 204 require.NoError(t, simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 205 206 app.Commit() 207 208 testCases := []appTestCase{ 209 { 210 msgs: []sdk.Msg{multiSendMsg2}, 211 accNums: []uint64{0}, 212 accSeqs: []uint64{0}, 213 expSimPass: true, 214 expPass: true, 215 privKeys: []cryptotypes.PrivKey{priv1}, 216 expectedBalances: []expectedBalance{ 217 {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, 218 {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 47)}}, 219 {addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}}, 220 }, 221 }, 222 } 223 224 for _, tc := range testCases { 225 header := tmproto.Header{Height: app.LastBlockHeight() + 1} 226 txGen := simapp.MakeTestEncodingConfig().TxConfig 227 _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...) 228 require.NoError(t, err) 229 230 for _, eb := range tc.expectedBalances { 231 simapp.CheckBalance(t, app, eb.addr, eb.coins) 232 } 233 } 234 } 235 236 func TestMsgMultiSendMultipleInOut(t *testing.T) { 237 acc1 := &authtypes.BaseAccount{ 238 Address: addr1.String(), 239 } 240 acc2 := &authtypes.BaseAccount{ 241 Address: addr2.String(), 242 } 243 acc4 := &authtypes.BaseAccount{ 244 Address: addr4.String(), 245 } 246 247 genAccs := []authtypes.GenesisAccount{acc1, acc2, acc4} 248 app := simapp.SetupWithGenesisAccounts(genAccs) 249 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 250 251 require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 252 253 require.NoError(t, simapp.FundAccount(app, ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 254 255 require.NoError(t, simapp.FundAccount(app, ctx, addr4, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 256 257 app.Commit() 258 259 testCases := []appTestCase{ 260 { 261 msgs: []sdk.Msg{multiSendMsg3}, 262 accNums: []uint64{0, 2}, 263 accSeqs: []uint64{0, 0}, 264 expSimPass: true, 265 expPass: true, 266 privKeys: []cryptotypes.PrivKey{priv1, priv4}, 267 expectedBalances: []expectedBalance{ 268 {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, 269 {addr4, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, 270 {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 52)}}, 271 {addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, 272 }, 273 }, 274 } 275 276 for _, tc := range testCases { 277 header := tmproto.Header{Height: app.LastBlockHeight() + 1} 278 txGen := simapp.MakeTestEncodingConfig().TxConfig 279 _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...) 280 require.NoError(t, err) 281 282 for _, eb := range tc.expectedBalances { 283 simapp.CheckBalance(t, app, eb.addr, eb.coins) 284 } 285 } 286 } 287 288 func TestMsgMultiSendDependent(t *testing.T) { 289 acc1 := authtypes.NewBaseAccountWithAddress(addr1) 290 acc2 := authtypes.NewBaseAccountWithAddress(addr2) 291 err := acc2.SetAccountNumber(1) 292 require.NoError(t, err) 293 294 genAccs := []authtypes.GenesisAccount{acc1, acc2} 295 app := simapp.SetupWithGenesisAccounts(genAccs) 296 ctx := app.BaseApp.NewContext(false, tmproto.Header{}) 297 298 require.NoError(t, simapp.FundAccount(app, ctx, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42)))) 299 300 app.Commit() 301 302 testCases := []appTestCase{ 303 { 304 msgs: []sdk.Msg{multiSendMsg1}, 305 accNums: []uint64{0}, 306 accSeqs: []uint64{0}, 307 expSimPass: true, 308 expPass: true, 309 privKeys: []cryptotypes.PrivKey{priv1}, 310 expectedBalances: []expectedBalance{ 311 {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, 312 {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, 313 }, 314 }, 315 { 316 msgs: []sdk.Msg{multiSendMsg4}, 317 accNums: []uint64{1}, 318 accSeqs: []uint64{0}, 319 expSimPass: true, 320 expPass: true, 321 privKeys: []cryptotypes.PrivKey{priv2}, 322 expectedBalances: []expectedBalance{ 323 {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 42)}}, 324 }, 325 }, 326 } 327 328 for _, tc := range testCases { 329 header := tmproto.Header{Height: app.LastBlockHeight() + 1} 330 txGen := simapp.MakeTestEncodingConfig().TxConfig 331 _, _, err := simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, tc.msgs, "", tc.accNums, tc.accSeqs, tc.expSimPass, tc.expPass, tc.privKeys...) 332 require.NoError(t, err) 333 334 for _, eb := range tc.expectedBalances { 335 simapp.CheckBalance(t, app, eb.addr, eb.coins) 336 } 337 } 338 }