2017-06-30 11:26:17 -07:00
|
|
|
package coin
|
|
|
|
|
|
|
|
import (
|
2017-07-03 09:58:28 -07:00
|
|
|
"encoding/json"
|
2017-06-30 11:26:17 -07:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2017-07-03 06:33:59 -07:00
|
|
|
"github.com/stretchr/testify/require"
|
2017-07-03 09:58:28 -07:00
|
|
|
|
|
|
|
crypto "github.com/tendermint/go-crypto"
|
|
|
|
"github.com/tendermint/tmlibs/log"
|
|
|
|
|
2017-06-30 11:26:17 -07:00
|
|
|
"github.com/tendermint/basecoin"
|
|
|
|
"github.com/tendermint/basecoin/stack"
|
|
|
|
"github.com/tendermint/basecoin/types"
|
|
|
|
)
|
|
|
|
|
2017-07-03 06:33:59 -07:00
|
|
|
// this makes sure that txs are rejected with invalid data or permissions
|
|
|
|
func TestHandlerValidation(t *testing.T) {
|
2017-06-30 11:26:17 -07:00
|
|
|
assert := assert.New(t)
|
|
|
|
|
|
|
|
// these are all valid, except for minusCoins
|
|
|
|
addr1 := basecoin.Actor{App: "coin", Address: []byte{1, 2}}
|
|
|
|
addr2 := basecoin.Actor{App: "role", Address: []byte{7, 8}}
|
|
|
|
someCoins := types.Coins{{"atom", 123}}
|
2017-07-03 06:33:59 -07:00
|
|
|
doubleCoins := types.Coins{{"atom", 246}}
|
2017-06-30 11:26:17 -07:00
|
|
|
minusCoins := types.Coins{{"eth", -34}}
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
valid bool
|
2017-07-03 06:33:59 -07:00
|
|
|
tx basecoin.Tx
|
2017-06-30 11:26:17 -07:00
|
|
|
perms []basecoin.Actor
|
|
|
|
}{
|
|
|
|
// auth works with different apps
|
|
|
|
{true,
|
2017-07-03 06:33:59 -07:00
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, someCoins)}),
|
2017-06-30 11:26:17 -07:00
|
|
|
[]basecoin.Actor{addr1}},
|
|
|
|
{true,
|
2017-07-03 06:33:59 -07:00
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr2, someCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr1, someCoins)}),
|
|
|
|
[]basecoin.Actor{addr1, addr2}},
|
|
|
|
// check multi-input with both sigs
|
|
|
|
{true,
|
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 2), NewTxInput(addr2, someCoins, 3)},
|
|
|
|
[]TxOutput{NewTxOutput(addr1, doubleCoins)}),
|
2017-06-30 11:26:17 -07:00
|
|
|
[]basecoin.Actor{addr1, addr2}},
|
|
|
|
// wrong permissions fail
|
|
|
|
{false,
|
2017-07-03 06:33:59 -07:00
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, someCoins)}),
|
2017-06-30 11:26:17 -07:00
|
|
|
[]basecoin.Actor{}},
|
|
|
|
{false,
|
2017-07-03 06:33:59 -07:00
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, someCoins)}),
|
2017-06-30 11:26:17 -07:00
|
|
|
[]basecoin.Actor{addr2}},
|
2017-07-03 06:33:59 -07:00
|
|
|
{false,
|
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 2), NewTxInput(addr2, someCoins, 3)},
|
|
|
|
[]TxOutput{NewTxOutput(addr1, doubleCoins)}),
|
|
|
|
[]basecoin.Actor{addr1}},
|
2017-06-30 11:26:17 -07:00
|
|
|
// invalid input fails
|
|
|
|
{false,
|
2017-07-03 06:33:59 -07:00
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, minusCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, minusCoins)}),
|
2017-06-30 11:26:17 -07:00
|
|
|
[]basecoin.Actor{addr2}},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range cases {
|
2017-07-03 08:32:01 -07:00
|
|
|
ctx := stack.MockContext("base-chain").WithPermissions(tc.perms...)
|
2017-07-03 06:33:59 -07:00
|
|
|
_, err := checkTx(ctx, tc.tx)
|
2017-06-30 11:26:17 -07:00
|
|
|
if tc.valid {
|
|
|
|
assert.Nil(err, "%d: %+v", i, err)
|
|
|
|
} else {
|
|
|
|
assert.NotNil(err, "%d", i)
|
|
|
|
}
|
2017-07-03 06:33:59 -07:00
|
|
|
}
|
|
|
|
}
|
2017-06-30 11:26:17 -07:00
|
|
|
|
2017-07-03 06:33:59 -07:00
|
|
|
func TestDeliverTx(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
// some sample settings
|
|
|
|
addr1 := basecoin.Actor{App: "coin", Address: []byte{1, 2}}
|
|
|
|
addr2 := basecoin.Actor{App: "role", Address: []byte{7, 8}}
|
|
|
|
addr3 := basecoin.Actor{App: "coin", Address: []byte{6, 5, 4, 3}}
|
|
|
|
|
|
|
|
someCoins := types.Coins{{"atom", 123}}
|
|
|
|
moreCoins := types.Coins{{"atom", 6487}}
|
|
|
|
diffCoins := moreCoins.Minus(someCoins)
|
|
|
|
otherCoins := types.Coins{{"eth", 11}}
|
|
|
|
mixedCoins := someCoins.Plus(otherCoins)
|
|
|
|
|
|
|
|
type money struct {
|
|
|
|
addr basecoin.Actor
|
|
|
|
coins types.Coins
|
|
|
|
}
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
init []money
|
|
|
|
tx basecoin.Tx
|
|
|
|
perms []basecoin.Actor
|
|
|
|
final []money // nil for error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
[]money{{addr1, moreCoins}},
|
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, someCoins, 1)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, someCoins)}),
|
|
|
|
[]basecoin.Actor{addr1},
|
|
|
|
[]money{{addr1, diffCoins}, {addr2, someCoins}},
|
|
|
|
},
|
|
|
|
// simple multi-sig 2 accounts to 1
|
|
|
|
{
|
|
|
|
[]money{{addr1, mixedCoins}, {addr2, moreCoins}},
|
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, otherCoins, 1), NewTxInput(addr2, someCoins, 1)},
|
|
|
|
[]TxOutput{NewTxOutput(addr3, mixedCoins)}),
|
|
|
|
[]basecoin.Actor{addr1, addr2},
|
|
|
|
[]money{{addr1, someCoins}, {addr2, diffCoins}, {addr3, mixedCoins}},
|
|
|
|
},
|
|
|
|
// multi-sig with one account sending many times
|
|
|
|
{
|
|
|
|
[]money{{addr1, moreCoins.Plus(otherCoins)}},
|
|
|
|
NewSendTx(
|
|
|
|
[]TxInput{NewTxInput(addr1, otherCoins, 1), NewTxInput(addr1, someCoins, 2)},
|
|
|
|
[]TxOutput{NewTxOutput(addr2, mixedCoins)}),
|
|
|
|
[]basecoin.Actor{addr1},
|
|
|
|
[]money{{addr1, diffCoins}, {addr2, mixedCoins}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
h := NewHandler()
|
|
|
|
for i, tc := range cases {
|
|
|
|
// setup the cases....
|
|
|
|
store := types.NewMemKVStore()
|
|
|
|
for _, m := range tc.init {
|
|
|
|
acct := Account{Coins: m.coins}
|
2017-07-03 12:34:08 -07:00
|
|
|
err := storeAccount(store, h.MakeKey(m.addr), acct)
|
2017-07-03 06:33:59 -07:00
|
|
|
require.Nil(err, "%d: %+v", i, err)
|
|
|
|
}
|
|
|
|
|
2017-07-03 08:32:01 -07:00
|
|
|
ctx := stack.MockContext("base-chain").WithPermissions(tc.perms...)
|
2017-07-03 06:33:59 -07:00
|
|
|
_, err := h.DeliverTx(ctx, store, tc.tx)
|
|
|
|
if len(tc.final) > 0 { // valid
|
2017-06-30 11:26:17 -07:00
|
|
|
assert.Nil(err, "%d: %+v", i, err)
|
2017-07-03 06:33:59 -07:00
|
|
|
// make sure the final balances are correct
|
|
|
|
for _, f := range tc.final {
|
2017-07-03 12:34:08 -07:00
|
|
|
acct, err := loadAccount(store, h.MakeKey(f.addr))
|
2017-07-03 06:33:59 -07:00
|
|
|
assert.Nil(err, "%d: %+v", i, err)
|
|
|
|
assert.Equal(f.coins, acct.Coins)
|
|
|
|
}
|
2017-06-30 11:26:17 -07:00
|
|
|
} else {
|
|
|
|
assert.NotNil(err, "%d", i)
|
2017-07-03 06:33:59 -07:00
|
|
|
// TODO: make sure balances unchanged!
|
2017-06-30 11:26:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-07-03 09:58:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetOption(t *testing.T) {
|
|
|
|
assert := assert.New(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
// some sample settings
|
|
|
|
pk := crypto.GenPrivKeySecp256k1().Wrap()
|
|
|
|
addr := pk.PubKey().Address()
|
2017-07-04 03:22:06 -07:00
|
|
|
actor := basecoin.Actor{App: stack.NameSigs, Address: addr}
|
2017-07-03 09:58:28 -07:00
|
|
|
|
|
|
|
someCoins := types.Coins{{"atom", 123}}
|
|
|
|
otherCoins := types.Coins{{"eth", 11}}
|
|
|
|
mixedCoins := someCoins.Plus(otherCoins)
|
|
|
|
|
|
|
|
type money struct {
|
|
|
|
addr basecoin.Actor
|
|
|
|
coins types.Coins
|
|
|
|
}
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
init []GenesisAccount
|
|
|
|
expected []money
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
[]GenesisAccount{{Address: addr, Balance: mixedCoins}},
|
|
|
|
[]money{{actor, mixedCoins}},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
h := NewHandler()
|
|
|
|
l := log.NewNopLogger()
|
|
|
|
for i, tc := range cases {
|
|
|
|
store := types.NewMemKVStore()
|
2017-07-04 03:22:06 -07:00
|
|
|
key := "account"
|
2017-07-03 09:58:28 -07:00
|
|
|
|
|
|
|
// set the options
|
|
|
|
for j, gen := range tc.init {
|
|
|
|
value, err := json.Marshal(gen)
|
|
|
|
require.Nil(err, "%d,%d: %+v", i, j, err)
|
2017-07-04 03:22:06 -07:00
|
|
|
_, err = h.SetOption(l, store, NameCoin, key, string(value))
|
2017-07-03 09:58:28 -07:00
|
|
|
require.Nil(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check state is proper
|
|
|
|
for _, f := range tc.expected {
|
2017-07-03 12:34:08 -07:00
|
|
|
acct, err := loadAccount(store, h.MakeKey(f.addr))
|
2017-07-03 09:58:28 -07:00
|
|
|
assert.Nil(err, "%d: %+v", i, err)
|
|
|
|
assert.Equal(f.coins, acct.Coins)
|
|
|
|
}
|
|
|
|
}
|
2017-07-03 06:33:59 -07:00
|
|
|
|
2017-06-30 11:26:17 -07:00
|
|
|
}
|