PoW InitGenesis; testcases

This commit is contained in:
Christopher Goes 2018-04-05 15:16:54 +02:00
parent d47f271459
commit d99f4f3c14
No known key found for this signature in database
GPG Key ID: E828D98232D328D3
9 changed files with 62 additions and 31 deletions

View File

@ -77,7 +77,7 @@ func NewDemocoinApp(logger log.Logger, dbs map[string]dbm.DB) *DemocoinApp {
// initialize BaseApp
app.SetTxDecoder(app.txDecoder)
app.SetInitChainer(app.initChainerFn(coolKeeper))
app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper))
app.MountStoreWithDB(app.capKeyMainStore, sdk.StoreTypeIAVL, dbs["main"])
app.MountStoreWithDB(app.capKeyAccountStore, sdk.StoreTypeIAVL, dbs["acc"])
app.MountStoreWithDB(app.capKeyPowStore, sdk.StoreTypeIAVL, dbs["pow"])
@ -151,7 +151,7 @@ func (app *DemocoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) {
}
// custom logic for democoin initialization
func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper) sdk.InitChainer {
func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keeper) sdk.InitChainer {
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.AppStateBytes
@ -172,7 +172,13 @@ func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper) sdk.InitChainer {
}
// Application specific genesis handling
err = coolKeeper.InitGenesis(ctx, stateJSON)
err = coolKeeper.InitGenesis(ctx, genesisState.CoolGenesis)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "")
}
err = powKeeper.InitGenesis(ctx, genesisState.PowGenesis)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "")

View File

@ -260,6 +260,10 @@ func TestMineMsg(t *testing.T) {
"cool": map[string]string{
"trend": "ice-cold",
},
"pow": map[string]uint64{
"difficulty": 1,
"count": 0,
},
}
stateBytes, err := json.MarshalIndent(genesisState, "", "\t")
require.Nil(t, err)
@ -279,11 +283,12 @@ func TestMineMsg(t *testing.T) {
SignCheckDeliver(t, bapp, mineMsg1, 0, true)
CheckBalance(t, bapp, "1pow")
// Mine again and check for reward
/*
mineMsg2 := pow.GenerateMineMsg(addr1, 2, 2)
SignCheckDeliver(t, bapp, mineMsg2, 1, true)
CheckBalance(t, bapp, "2pow")
*/
mineMsg2 := pow.GenerateMineMsg(addr1, 2, 3)
SignCheckDeliver(t, bapp, mineMsg2, 1, true)
CheckBalance(t, bapp, "2pow")
// Mine again - should be invalid
SignCheckDeliver(t, bapp, mineMsg2, 1, false)
CheckBalance(t, bapp, "2pow")
}

View File

@ -4,6 +4,9 @@ import (
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/examples/democoin/x/cool"
"github.com/cosmos/cosmos-sdk/examples/democoin/x/pow"
)
var _ sdk.Account = (*AppAccount)(nil)
@ -41,7 +44,9 @@ func GetAccountDecoder(cdc *wire.Codec) sdk.AccountDecoder {
// State to Unmarshal
type GenesisState struct {
Accounts []*GenesisAccount `json:"accounts"`
Accounts []*GenesisAccount `json:"accounts"`
PowGenesis pow.PowGenesis `json:"pow"`
CoolGenesis cool.CoolGenesis `json:"cool"`
}
// GenesisAccount doesn't need pubkey or sequence

View File

@ -1,17 +1,10 @@
package cool
import (
"encoding/json"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank"
)
// Cool genesis state, containing the genesis trend
type GenesisState struct {
trend string
}
// Keeper - handlers sets/gets of custom variables for your module
type Keeper struct {
ck bank.CoinKeeper
@ -49,11 +42,7 @@ func (k Keeper) CheckTrend(ctx sdk.Context, guessedTrend string) bool {
}
// InitGenesis - store the genesis trend
func (k Keeper) InitGenesis(ctx sdk.Context, data json.RawMessage) error {
var state GenesisState
if err := json.Unmarshal(data, &state); err != nil {
return err
}
k.setTrend(ctx, state.trend)
func (k Keeper) InitGenesis(ctx sdk.Context, data CoolGenesis) error {
k.setTrend(ctx, data.Trend)
return nil
}

View File

@ -15,6 +15,11 @@ type SetTrendMsg struct {
Cool string
}
// Genesis state - specify genesis trend
type CoolGenesis struct {
Trend string `json:"trend"`
}
// New cool message
func NewSetTrendMsg(sender sdk.Address, cool string) SetTrendMsg {
return SetTrendMsg{

View File

@ -25,9 +25,13 @@ func handleMineMsg(ctx sdk.Context, pk Keeper, msg MineMsg) sdk.Result {
return err.Result()
}
if ctx.IsCheckTx() {
return sdk.Result{} // TODO
}
// commented for now, makes testing difficult
// TODO figure out a better test method that allows early CheckTx return
/*
if ctx.IsCheckTx() {
return sdk.Result{} // TODO
}
*/
err = pk.ApplyValid(ctx, msg.Sender, newDiff, newCount)
if err != nil {

View File

@ -26,6 +26,10 @@ func TestPowHandler(t *testing.T) {
addr := sdk.Address([]byte("sender"))
count := uint64(1)
difficulty := uint64(2)
err := keeper.InitGenesis(ctx, PowGenesis{uint64(1), uint64(0)})
assert.Nil(t, err)
nonce, proof := mine(addr, count, difficulty)
msg := NewMineMsg(addr, difficulty, count, nonce, proof)

View File

@ -14,8 +14,10 @@ type PowConfig struct {
Reward int64
}
func NewPowConfig(denomination string, reward int64) PowConfig {
return PowConfig{denomination, reward}
// genesis info must specify starting difficulty and starting count
type PowGenesis struct {
Difficulty uint64 `json:"difficulty"`
Count uint64 `json:"count"`
}
type Keeper struct {
@ -24,19 +26,27 @@ type Keeper struct {
ck bank.CoinKeeper
}
func NewPowConfig(denomination string, reward int64) PowConfig {
return PowConfig{denomination, reward}
}
func NewKeeper(key sdk.StoreKey, config PowConfig, ck bank.CoinKeeper) Keeper {
return Keeper{key, config, ck}
}
func (pk Keeper) InitGenesis(ctx sdk.Context, genesis PowGenesis) error {
pk.SetLastDifficulty(ctx, genesis.Difficulty)
pk.SetLastCount(ctx, genesis.Count)
return nil
}
var lastDifficultyKey = []byte("lastDifficultyKey")
func (pk Keeper) GetLastDifficulty(ctx sdk.Context) (uint64, error) {
store := ctx.KVStore(pk.key)
stored := store.Get(lastDifficultyKey)
if stored == nil {
// return the default difficulty of 1 if not set
// this works OK for this module, but a way to initalize the store (a "genesis block" for the module) might be better in general
return uint64(1), nil
panic("no stored difficulty")
} else {
return strconv.ParseUint(string(stored), 0, 64)
}
@ -53,7 +63,7 @@ func (pk Keeper) GetLastCount(ctx sdk.Context) (uint64, error) {
store := ctx.KVStore(pk.key)
stored := store.Get(countKey)
if stored == nil {
return uint64(0), nil
panic("no stored count")
} else {
return strconv.ParseUint(string(stored), 0, 64)
}

View File

@ -34,6 +34,9 @@ func TestPowKeeperGetSet(t *testing.T) {
ck := bank.NewCoinKeeper(am)
keeper := NewKeeper(capKey, config, ck)
err := keeper.InitGenesis(ctx, PowGenesis{uint64(1), uint64(0)})
assert.Nil(t, err)
res, err := keeper.GetLastDifficulty(ctx)
assert.Nil(t, err)
assert.Equal(t, res, uint64(1))