mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-25 15:55:18 +00:00
add kava app
This commit is contained in:
parent
9852e944d8
commit
ab8528e85f
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Kava
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
go install ./kava/cmd/kavad
|
||||||
|
go install ./kava/cmd/kavacli
|
145
kava/app/app.go
Normal file
145
kava/app/app.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
|
||||||
|
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/ibc"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/kava/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
appName = "BasecoinApp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Extended ABCI application
|
||||||
|
type BasecoinApp struct {
|
||||||
|
*bam.BaseApp
|
||||||
|
cdc *wire.Codec
|
||||||
|
|
||||||
|
// keys to access the substores
|
||||||
|
keyMain *sdk.KVStoreKey
|
||||||
|
keyAccount *sdk.KVStoreKey
|
||||||
|
keyIBC *sdk.KVStoreKey
|
||||||
|
keyStake *sdk.KVStoreKey
|
||||||
|
|
||||||
|
// Manage getting and setting accounts
|
||||||
|
accountMapper sdk.AccountMapper
|
||||||
|
coinKeeper bank.Keeper
|
||||||
|
ibcMapper ibc.Mapper
|
||||||
|
stakeKeeper stake.Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
|
||||||
|
|
||||||
|
// Create app-level codec for txs and accounts.
|
||||||
|
var cdc = MakeCodec()
|
||||||
|
|
||||||
|
// Create your application object.
|
||||||
|
var app = &BasecoinApp{
|
||||||
|
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
|
||||||
|
cdc: cdc,
|
||||||
|
keyMain: sdk.NewKVStoreKey("main"),
|
||||||
|
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||||
|
keyIBC: sdk.NewKVStoreKey("ibc"),
|
||||||
|
keyStake: sdk.NewKVStoreKey("stake"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the accountMapper.
|
||||||
|
app.accountMapper = auth.NewAccountMapper(
|
||||||
|
cdc,
|
||||||
|
app.keyAccount, // target store
|
||||||
|
&types.AppAccount{}, // prototype
|
||||||
|
)
|
||||||
|
|
||||||
|
// add accountMapper/handlers
|
||||||
|
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||||
|
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||||
|
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||||
|
|
||||||
|
// register message routes
|
||||||
|
app.Router().
|
||||||
|
AddRoute("bank", bank.NewHandler(app.coinKeeper)).
|
||||||
|
AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
|
||||||
|
AddRoute("stake", stake.NewHandler(app.stakeKeeper))
|
||||||
|
|
||||||
|
// Initialize BaseApp.
|
||||||
|
app.SetInitChainer(app.initChainer)
|
||||||
|
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake)
|
||||||
|
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.BurnFeeHandler))
|
||||||
|
err := app.LoadLatestVersion(app.keyMain)
|
||||||
|
if err != nil {
|
||||||
|
cmn.Exit(err.Error())
|
||||||
|
}
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom tx codec
|
||||||
|
func MakeCodec() *wire.Codec {
|
||||||
|
var cdc = wire.NewCodec()
|
||||||
|
wire.RegisterCrypto(cdc) // Register crypto.
|
||||||
|
sdk.RegisterWire(cdc) // Register Msgs
|
||||||
|
bank.RegisterWire(cdc)
|
||||||
|
stake.RegisterWire(cdc)
|
||||||
|
ibc.RegisterWire(cdc)
|
||||||
|
|
||||||
|
// register custom AppAccount
|
||||||
|
cdc.RegisterInterface((*sdk.Account)(nil), nil)
|
||||||
|
cdc.RegisterConcrete(&types.AppAccount{}, "basecoin/Account", nil)
|
||||||
|
return cdc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom logic for basecoin initialization
|
||||||
|
func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||||
|
stateJSON := req.AppStateBytes
|
||||||
|
|
||||||
|
genesisState := new(types.GenesisState)
|
||||||
|
err := app.cdc.UnmarshalJSON(stateJSON, genesisState)
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||||
|
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, gacc := range genesisState.Accounts {
|
||||||
|
acc, err := gacc.ToAppAccount()
|
||||||
|
if err != nil {
|
||||||
|
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||||
|
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||||
|
}
|
||||||
|
app.accountMapper.SetAccount(ctx, acc)
|
||||||
|
}
|
||||||
|
return abci.ResponseInitChain{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom logic for state export
|
||||||
|
func (app *BasecoinApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
||||||
|
ctx := app.NewContext(true, abci.Header{})
|
||||||
|
|
||||||
|
// iterate to get the accounts
|
||||||
|
accounts := []*types.GenesisAccount{}
|
||||||
|
appendAccount := func(acc sdk.Account) (stop bool) {
|
||||||
|
account := &types.GenesisAccount{
|
||||||
|
Address: acc.GetAddress(),
|
||||||
|
Coins: acc.GetCoins(),
|
||||||
|
}
|
||||||
|
accounts = append(accounts, account)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
app.accountMapper.IterateAccounts(ctx, appendAccount)
|
||||||
|
|
||||||
|
genState := types.GenesisState{
|
||||||
|
Accounts: accounts,
|
||||||
|
}
|
||||||
|
return wire.MarshalJSONIndent(app.cdc, genState)
|
||||||
|
}
|
461
kava/app/app_test.go
Normal file
461
kava/app/app_test.go
Normal file
@ -0,0 +1,461 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/ibc"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
crypto "github.com/tendermint/go-crypto"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Construct some global addrs and txs for tests.
|
||||||
|
var (
|
||||||
|
chainID = "" // TODO
|
||||||
|
|
||||||
|
accName = "foobart"
|
||||||
|
|
||||||
|
priv1 = crypto.GenPrivKeyEd25519()
|
||||||
|
addr1 = priv1.PubKey().Address()
|
||||||
|
priv2 = crypto.GenPrivKeyEd25519()
|
||||||
|
addr2 = priv2.PubKey().Address()
|
||||||
|
addr3 = crypto.GenPrivKeyEd25519().PubKey().Address()
|
||||||
|
priv4 = crypto.GenPrivKeyEd25519()
|
||||||
|
addr4 = priv4.PubKey().Address()
|
||||||
|
coins = sdk.Coins{{"foocoin", 10}}
|
||||||
|
halfCoins = sdk.Coins{{"foocoin", 5}}
|
||||||
|
manyCoins = sdk.Coins{{"foocoin", 1}, {"barcoin", 1}}
|
||||||
|
fee = sdk.StdFee{
|
||||||
|
sdk.Coins{{"foocoin", 0}},
|
||||||
|
0,
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMsg1 = bank.MsgSend{
|
||||||
|
Inputs: []bank.Input{bank.NewInput(addr1, coins)},
|
||||||
|
Outputs: []bank.Output{bank.NewOutput(addr2, coins)},
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMsg2 = bank.MsgSend{
|
||||||
|
Inputs: []bank.Input{bank.NewInput(addr1, coins)},
|
||||||
|
Outputs: []bank.Output{
|
||||||
|
bank.NewOutput(addr2, halfCoins),
|
||||||
|
bank.NewOutput(addr3, halfCoins),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMsg3 = bank.MsgSend{
|
||||||
|
Inputs: []bank.Input{
|
||||||
|
bank.NewInput(addr1, coins),
|
||||||
|
bank.NewInput(addr4, coins),
|
||||||
|
},
|
||||||
|
Outputs: []bank.Output{
|
||||||
|
bank.NewOutput(addr2, coins),
|
||||||
|
bank.NewOutput(addr3, coins),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMsg4 = bank.MsgSend{
|
||||||
|
Inputs: []bank.Input{
|
||||||
|
bank.NewInput(addr2, coins),
|
||||||
|
},
|
||||||
|
Outputs: []bank.Output{
|
||||||
|
bank.NewOutput(addr1, coins),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMsg5 = bank.MsgSend{
|
||||||
|
Inputs: []bank.Input{
|
||||||
|
bank.NewInput(addr1, manyCoins),
|
||||||
|
},
|
||||||
|
Outputs: []bank.Output{
|
||||||
|
bank.NewOutput(addr2, manyCoins),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func loggerAndDB() (log.Logger, dbm.DB) {
|
||||||
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
||||||
|
db := dbm.NewMemDB()
|
||||||
|
return logger, db
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBasecoinApp() *BasecoinApp {
|
||||||
|
logger, db := loggerAndDB()
|
||||||
|
return NewBasecoinApp(logger, db)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setGenesisAccounts(bapp *BasecoinApp, accs ...auth.BaseAccount) error {
|
||||||
|
genaccs := make([]*types.GenesisAccount, len(accs))
|
||||||
|
for i, acc := range accs {
|
||||||
|
genaccs[i] = types.NewGenesisAccount(&types.AppAccount{acc, accName})
|
||||||
|
}
|
||||||
|
|
||||||
|
genesisState := types.GenesisState{
|
||||||
|
Accounts: genaccs,
|
||||||
|
}
|
||||||
|
|
||||||
|
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the chain
|
||||||
|
vals := []abci.Validator{}
|
||||||
|
bapp.InitChain(abci.RequestInitChain{vals, stateBytes})
|
||||||
|
bapp.Commit()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//_______________________________________________________________________
|
||||||
|
|
||||||
|
func TestMsgs(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
msgs := []struct {
|
||||||
|
msg sdk.Msg
|
||||||
|
}{
|
||||||
|
{sendMsg1},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range msgs {
|
||||||
|
// Run a CheckDeliver
|
||||||
|
SignCheckDeliver(t, bapp, m.msg, []int64{int64(i)}, false, priv1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSortGenesis(t *testing.T) {
|
||||||
|
logger, db := loggerAndDB()
|
||||||
|
bapp := NewBasecoinApp(logger, db)
|
||||||
|
|
||||||
|
// Note the order: the coins are unsorted!
|
||||||
|
coinDenom1, coinDenom2 := "foocoin", "barcoin"
|
||||||
|
|
||||||
|
genState := fmt.Sprintf(`{
|
||||||
|
"accounts": [{
|
||||||
|
"address": "%s",
|
||||||
|
"coins": [
|
||||||
|
{
|
||||||
|
"denom": "%s",
|
||||||
|
"amount": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"denom": "%s",
|
||||||
|
"amount": 20
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}`, addr1.String(), coinDenom1, coinDenom2)
|
||||||
|
|
||||||
|
// Initialize the chain
|
||||||
|
vals := []abci.Validator{}
|
||||||
|
bapp.InitChain(abci.RequestInitChain{vals, []byte(genState)})
|
||||||
|
bapp.Commit()
|
||||||
|
|
||||||
|
// Unsorted coins means invalid
|
||||||
|
err := sendMsg5.ValidateBasic()
|
||||||
|
require.Equal(t, sdk.CodeInvalidCoins, err.Code(), err.ABCILog())
|
||||||
|
|
||||||
|
// Sort coins, should be valid
|
||||||
|
sendMsg5.Inputs[0].Coins.Sort()
|
||||||
|
sendMsg5.Outputs[0].Coins.Sort()
|
||||||
|
err = sendMsg5.ValidateBasic()
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Ensure we can send
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg5, []int64{0}, true, priv1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenesis(t *testing.T) {
|
||||||
|
logger, db := loggerAndDB()
|
||||||
|
bapp := NewBasecoinApp(logger, db)
|
||||||
|
|
||||||
|
// Construct some genesis bytes to reflect basecoin/types/AppAccount
|
||||||
|
pk := crypto.GenPrivKeyEd25519().PubKey()
|
||||||
|
addr := pk.Address()
|
||||||
|
coins, err := sdk.ParseCoins("77foocoin,99barcoin")
|
||||||
|
require.Nil(t, err)
|
||||||
|
baseAcc := auth.BaseAccount{
|
||||||
|
Address: addr,
|
||||||
|
Coins: coins,
|
||||||
|
}
|
||||||
|
acc := &types.AppAccount{baseAcc, "foobart"}
|
||||||
|
|
||||||
|
err = setGenesisAccounts(bapp, baseAcc)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// A checkTx context
|
||||||
|
ctx := bapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
res1 := bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
|
||||||
|
assert.Equal(t, acc, res1)
|
||||||
|
|
||||||
|
// reload app and ensure the account is still there
|
||||||
|
bapp = NewBasecoinApp(logger, db)
|
||||||
|
ctx = bapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
res1 = bapp.accountMapper.GetAccount(ctx, baseAcc.Address)
|
||||||
|
assert.Equal(t, acc, res1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMsgSendWithAccounts(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
// Construct some genesis bytes to reflect basecoin/types/AppAccount
|
||||||
|
// Give 77 foocoin to the first key
|
||||||
|
coins, err := sdk.ParseCoins("77foocoin")
|
||||||
|
require.Nil(t, err)
|
||||||
|
baseAcc := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: coins,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct genesis state
|
||||||
|
err = setGenesisAccounts(bapp, baseAcc)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
// A checkTx context (true)
|
||||||
|
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)
|
||||||
|
assert.Equal(t, baseAcc, res1.(*types.AppAccount).BaseAccount)
|
||||||
|
|
||||||
|
// Run a CheckDeliver
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg1, []int64{0}, true, priv1)
|
||||||
|
|
||||||
|
// Check balances
|
||||||
|
CheckBalance(t, bapp, addr1, "67foocoin")
|
||||||
|
CheckBalance(t, bapp, addr2, "10foocoin")
|
||||||
|
|
||||||
|
// Delivering again should cause replay error
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg1, []int64{0}, false, priv1)
|
||||||
|
|
||||||
|
// bumping the txnonce number without resigning should be an auth error
|
||||||
|
tx := genTx(sendMsg1, []int64{0}, priv1)
|
||||||
|
tx.Signatures[0].Sequence = 1
|
||||||
|
res := bapp.Deliver(tx)
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||||
|
|
||||||
|
// resigning the tx with the bumped sequence should work
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg1, []int64{1}, true, priv1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMsgSendMultipleOut(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
genCoins, err := sdk.ParseCoins("42foocoin")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
acc1 := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc2 := auth.BaseAccount{
|
||||||
|
Address: addr2,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setGenesisAccounts(bapp, acc1, acc2)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// Simulate a Block
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg2, []int64{0}, true, priv1)
|
||||||
|
|
||||||
|
// Check balances
|
||||||
|
CheckBalance(t, bapp, addr1, "32foocoin")
|
||||||
|
CheckBalance(t, bapp, addr2, "47foocoin")
|
||||||
|
CheckBalance(t, bapp, addr3, "5foocoin")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSengMsgMultipleInOut(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
genCoins, err := sdk.ParseCoins("42foocoin")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
acc1 := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc2 := auth.BaseAccount{
|
||||||
|
Address: addr2,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc4 := auth.BaseAccount{
|
||||||
|
Address: addr4,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setGenesisAccounts(bapp, acc1, acc2, acc4)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// CheckDeliver
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg3, []int64{0, 0}, true, priv1, priv4)
|
||||||
|
|
||||||
|
// Check balances
|
||||||
|
CheckBalance(t, bapp, addr1, "32foocoin")
|
||||||
|
CheckBalance(t, bapp, addr4, "32foocoin")
|
||||||
|
CheckBalance(t, bapp, addr2, "52foocoin")
|
||||||
|
CheckBalance(t, bapp, addr3, "10foocoin")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMsgSendDependent(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
genCoins, err := sdk.ParseCoins("42foocoin")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
acc1 := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: genCoins,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setGenesisAccounts(bapp, acc1)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// CheckDeliver
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg1, []int64{0}, true, priv1)
|
||||||
|
|
||||||
|
// Check balances
|
||||||
|
CheckBalance(t, bapp, addr1, "32foocoin")
|
||||||
|
CheckBalance(t, bapp, addr2, "10foocoin")
|
||||||
|
|
||||||
|
// Simulate a Block
|
||||||
|
SignCheckDeliver(t, bapp, sendMsg4, []int64{0}, true, priv2)
|
||||||
|
|
||||||
|
// Check balances
|
||||||
|
CheckBalance(t, bapp, addr1, "42foocoin")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMsgQuiz(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
// Construct genesis state
|
||||||
|
// Construct some genesis bytes to reflect basecoin/types/AppAccount
|
||||||
|
baseAcc := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: nil,
|
||||||
|
}
|
||||||
|
acc1 := &types.AppAccount{baseAcc, "foobart"}
|
||||||
|
|
||||||
|
// Construct genesis state
|
||||||
|
genesisState := map[string]interface{}{
|
||||||
|
"accounts": []*types.GenesisAccount{
|
||||||
|
types.NewGenesisAccount(acc1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Initialize the chain (nil)
|
||||||
|
vals := []abci.Validator{}
|
||||||
|
bapp.InitChain(abci.RequestInitChain{vals, stateBytes})
|
||||||
|
bapp.Commit()
|
||||||
|
|
||||||
|
// A checkTx context (true)
|
||||||
|
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)
|
||||||
|
assert.Equal(t, acc1, res1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIBCMsgs(t *testing.T) {
|
||||||
|
bapp := newBasecoinApp()
|
||||||
|
|
||||||
|
sourceChain := "source-chain"
|
||||||
|
destChain := "dest-chain"
|
||||||
|
|
||||||
|
baseAcc := auth.BaseAccount{
|
||||||
|
Address: addr1,
|
||||||
|
Coins: coins,
|
||||||
|
}
|
||||||
|
acc1 := &types.AppAccount{baseAcc, "foobart"}
|
||||||
|
|
||||||
|
err := setGenesisAccounts(bapp, baseAcc)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
// A checkTx context (true)
|
||||||
|
ctxCheck := bapp.BaseApp.NewContext(true, abci.Header{})
|
||||||
|
res1 := bapp.accountMapper.GetAccount(ctxCheck, addr1)
|
||||||
|
assert.Equal(t, acc1, res1)
|
||||||
|
|
||||||
|
packet := ibc.IBCPacket{
|
||||||
|
SrcAddr: addr1,
|
||||||
|
DestAddr: addr1,
|
||||||
|
Coins: coins,
|
||||||
|
SrcChain: sourceChain,
|
||||||
|
DestChain: destChain,
|
||||||
|
}
|
||||||
|
|
||||||
|
transferMsg := ibc.IBCTransferMsg{
|
||||||
|
IBCPacket: packet,
|
||||||
|
}
|
||||||
|
|
||||||
|
receiveMsg := ibc.IBCReceiveMsg{
|
||||||
|
IBCPacket: packet,
|
||||||
|
Relayer: addr1,
|
||||||
|
Sequence: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
SignCheckDeliver(t, bapp, transferMsg, []int64{0}, true, priv1)
|
||||||
|
CheckBalance(t, bapp, addr1, "")
|
||||||
|
SignCheckDeliver(t, bapp, transferMsg, []int64{1}, false, priv1)
|
||||||
|
SignCheckDeliver(t, bapp, receiveMsg, []int64{2}, true, priv1)
|
||||||
|
CheckBalance(t, bapp, addr1, "10foocoin")
|
||||||
|
SignCheckDeliver(t, bapp, receiveMsg, []int64{3}, false, priv1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func genTx(msg sdk.Msg, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.StdTx {
|
||||||
|
sigs := make([]sdk.StdSignature, len(priv))
|
||||||
|
for i, p := range priv {
|
||||||
|
sigs[i] = sdk.StdSignature{
|
||||||
|
PubKey: p.PubKey(),
|
||||||
|
Signature: p.Sign(sdk.StdSignBytes(chainID, seq, fee, msg)),
|
||||||
|
Sequence: seq[i],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sdk.NewStdTx(msg, fee, sigs)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignCheckDeliver(t *testing.T, bapp *BasecoinApp, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
|
||||||
|
|
||||||
|
// Sign the tx
|
||||||
|
tx := genTx(msg, seq, priv...)
|
||||||
|
// Run a Check
|
||||||
|
res := bapp.Check(tx)
|
||||||
|
if expPass {
|
||||||
|
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||||
|
} else {
|
||||||
|
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate a Block
|
||||||
|
bapp.BeginBlock(abci.RequestBeginBlock{})
|
||||||
|
res = bapp.Deliver(tx)
|
||||||
|
if expPass {
|
||||||
|
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||||
|
} else {
|
||||||
|
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||||
|
}
|
||||||
|
bapp.EndBlock(abci.RequestEndBlock{})
|
||||||
|
//bapp.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckBalance(t *testing.T, bapp *BasecoinApp, addr sdk.Address, balExpected string) {
|
||||||
|
ctxDeliver := bapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
|
res2 := bapp.accountMapper.GetAccount(ctxDeliver, addr)
|
||||||
|
assert.Equal(t, balExpected, fmt.Sprintf("%v", res2.GetCoins()))
|
||||||
|
}
|
80
kava/cmd/kavacli/main.go
Normal file
80
kava/cmd/kavacli/main.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/tendermint/tmlibs/cli"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/lcd"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
|
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||||
|
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||||
|
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
|
||||||
|
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
|
||||||
|
|
||||||
|
"github.com/kava-labs/kava/kava/app"
|
||||||
|
"github.com/kava-labs/kava/kava/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// rootCmd is the entry point for this binary
|
||||||
|
var (
|
||||||
|
rootCmd = &cobra.Command{
|
||||||
|
Use: "basecli",
|
||||||
|
Short: "Basecoin light-client",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// disable sorting
|
||||||
|
cobra.EnableCommandSorting = false
|
||||||
|
|
||||||
|
// get the codec
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
|
||||||
|
// TODO: setup keybase, viper object, etc. to be passed into
|
||||||
|
// the below functions and eliminate global vars, like we do
|
||||||
|
// with the cdc
|
||||||
|
|
||||||
|
// add standard rpc, and tx commands
|
||||||
|
rpc.AddCommands(rootCmd)
|
||||||
|
rootCmd.AddCommand(client.LineBreak)
|
||||||
|
tx.AddCommands(rootCmd, cdc)
|
||||||
|
rootCmd.AddCommand(client.LineBreak)
|
||||||
|
|
||||||
|
// add query/post commands (custom to binary)
|
||||||
|
rootCmd.AddCommand(
|
||||||
|
client.GetCommands(
|
||||||
|
authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)),
|
||||||
|
)...)
|
||||||
|
|
||||||
|
rootCmd.AddCommand(
|
||||||
|
client.PostCommands(
|
||||||
|
bankcmd.SendTxCmd(cdc),
|
||||||
|
ibccmd.IBCTransferCmd(cdc),
|
||||||
|
ibccmd.IBCRelayCmd(cdc),
|
||||||
|
stakecmd.GetCmdDeclareCandidacy(cdc),
|
||||||
|
stakecmd.GetCmdEditCandidacy(cdc),
|
||||||
|
stakecmd.GetCmdDelegate(cdc),
|
||||||
|
stakecmd.GetCmdUnbond(cdc),
|
||||||
|
)...)
|
||||||
|
|
||||||
|
// add proxy, version and key info
|
||||||
|
rootCmd.AddCommand(
|
||||||
|
client.LineBreak,
|
||||||
|
lcd.ServeCommand(cdc),
|
||||||
|
keys.Commands(),
|
||||||
|
client.LineBreak,
|
||||||
|
version.VersionCmd,
|
||||||
|
)
|
||||||
|
|
||||||
|
// prepare and add flags
|
||||||
|
executor := cli.PrepareMainCmd(rootCmd, "BC", os.ExpandEnv("$HOME/.basecli"))
|
||||||
|
executor.Execute()
|
||||||
|
}
|
45
kava/cmd/kavad/main.go
Normal file
45
kava/cmd/kavad/main.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tmlibs/cli"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
"github.com/kava-labs/kava/kava/app"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
ctx := server.NewDefaultContext()
|
||||||
|
|
||||||
|
rootCmd := &cobra.Command{
|
||||||
|
Use: "basecoind",
|
||||||
|
Short: "Basecoin Daemon (server)",
|
||||||
|
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||||
|
}
|
||||||
|
|
||||||
|
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit,
|
||||||
|
server.ConstructAppCreator(newApp, "basecoin"),
|
||||||
|
server.ConstructAppExporter(exportAppState, "basecoin"))
|
||||||
|
|
||||||
|
// prepare and add flags
|
||||||
|
rootDir := os.ExpandEnv("$HOME/.basecoind")
|
||||||
|
executor := cli.PrepareBaseCmd(rootCmd, "BC", rootDir)
|
||||||
|
executor.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||||
|
return app.NewBasecoinApp(logger, db)
|
||||||
|
}
|
||||||
|
|
||||||
|
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
||||||
|
bapp := app.NewBasecoinApp(logger, db)
|
||||||
|
return bapp.ExportAppStateJSON()
|
||||||
|
}
|
72
kava/types/account.go
Normal file
72
kava/types/account.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/wire"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ sdk.Account = (*AppAccount)(nil)
|
||||||
|
|
||||||
|
// Custom extensions for this application. This is just an example of
|
||||||
|
// extending auth.BaseAccount with custom fields.
|
||||||
|
//
|
||||||
|
// This is compatible with the stock auth.AccountStore, since
|
||||||
|
// auth.AccountStore uses the flexible go-amino library.
|
||||||
|
type AppAccount struct {
|
||||||
|
auth.BaseAccount
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
func (acc AppAccount) GetName() string { return acc.Name }
|
||||||
|
func (acc *AppAccount) SetName(name string) { acc.Name = name }
|
||||||
|
|
||||||
|
// Get the AccountDecoder function for the custom AppAccount
|
||||||
|
func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder {
|
||||||
|
return func(accBytes []byte) (res sdk.Account, err error) {
|
||||||
|
if len(accBytes) == 0 {
|
||||||
|
return nil, sdk.ErrTxDecode("accBytes are empty")
|
||||||
|
}
|
||||||
|
acct := new(AppAccount)
|
||||||
|
err = cdc.UnmarshalBinaryBare(accBytes, &acct)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return acct, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//___________________________________________________________________________________
|
||||||
|
|
||||||
|
// State to Unmarshal
|
||||||
|
type GenesisState struct {
|
||||||
|
Accounts []*GenesisAccount `json:"accounts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenesisAccount doesn't need pubkey or sequence
|
||||||
|
type GenesisAccount struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Address sdk.Address `json:"address"`
|
||||||
|
Coins sdk.Coins `json:"coins"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGenesisAccount(aa *AppAccount) *GenesisAccount {
|
||||||
|
return &GenesisAccount{
|
||||||
|
Name: aa.Name,
|
||||||
|
Address: aa.Address,
|
||||||
|
Coins: aa.Coins.Sort(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert GenesisAccount to AppAccount
|
||||||
|
func (ga *GenesisAccount) ToAppAccount() (acc *AppAccount, err error) {
|
||||||
|
baseAcc := auth.BaseAccount{
|
||||||
|
Address: ga.Address,
|
||||||
|
Coins: ga.Coins.Sort(),
|
||||||
|
}
|
||||||
|
return &AppAccount{
|
||||||
|
BaseAccount: baseAcc,
|
||||||
|
Name: ga.Name,
|
||||||
|
}, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user