Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New App structure #314

Merged
merged 6 commits into from
Jan 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
310 changes: 127 additions & 183 deletions app/app.go

Large diffs are not rendered by default.

73 changes: 46 additions & 27 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/abci/types"
"github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
)

func TestBasic(t *testing.T) {
Expand All @@ -24,31 +25,33 @@ func TestBasic(t *testing.T) {
}

// Create app.
app := sdk.NewApp(t.Name())
app.SetStore(mockMultiStore())
app.SetHandler(func(ctx Context, store MultiStore, tx Tx) Result {
app := NewApp(t.Name())
app.SetCommitMultiStore(newCommitMultiStore())
app.SetHandler(func(ctx types.Context, store types.MultiStore, tx types.Tx) types.Result {

// This could be a decorator.
fromJSON(ctx.TxBytes(), &tx)
var ttx testTx
fromJSON(ctx.TxBytes(), &ttx)

fmt.Println(">>", tx)
// XXX
return types.Result{}
})

// Load latest state, which should be empty.
err := app.LoadLatestVersion()
assert.Nil(t, err)
assert.Equal(t, app.NextVersion(), 1)
assert.Equal(t, app.LastBlockHeight(), int64(0))

// Create the validators
var numVals = 3
var valSet = make([]*abci.Validator, numVals)
var valSet = make([]abci.Validator, numVals)
for i := 0; i < numVals; i++ {
valSet[i] = makeVal(secret(i))
}

// Initialize the chain
app.InitChain(abci.RequestInitChain{
Validators: valset,
Validators: valSet,
})

// Simulate the start of a block.
Expand All @@ -62,24 +65,26 @@ func TestBasic(t *testing.T) {
}
txBytes := toJSON(tx)
res := app.DeliverTx(txBytes)
require.True(res.IsOK(), "%#v", res)
assert.True(t, res.IsOK(), "%#v", res)
}

// Simulate the end of a block.
// Get the summary of validator updates.
res := app.EndBlock(app.height)
res := app.EndBlock(abci.RequestEndBlock{})
valUpdates := res.ValidatorUpdates

// Assert that validator updates are correct.
for _, val := range valSet {
// Sanity
assert.NotEqual(t, len(val.PubKey), 0)

// Find matching update and splice it out.
for j := 0; j < len(valUpdates); {
assert.NotEqual(len(valUpdates.PubKey), 0)
valUpdate := valUpdates[j]

// Matched.
if bytes.Equal(valUpdate.PubKey, val.PubKey) {
assert.Equal(valUpdate.NewPower, val.Power+1)
assert.Equal(t, valUpdate.Power, val.Power+1)
if j < len(valUpdates)-1 {
// Splice it out.
valUpdates = append(valUpdates[:j], valUpdates[j+1:]...)
Expand All @@ -100,9 +105,9 @@ func randPower() int64 {
return cmn.RandInt64()
}

func makeVal(secret string) *abci.Validator {
return &abci.Validator{
PubKey: makePubKey(string).Bytes(),
func makeVal(secret string) abci.Validator {
return abci.Validator{
PubKey: makePubKey(secret).Bytes(),
Power: randPower(),
}
}
Expand All @@ -112,29 +117,43 @@ func makePubKey(secret string) crypto.PubKey {
}

func makePrivKey(secret string) crypto.PrivKey {
return crypto.GenPrivKeyEd25519FromSecret([]byte(id))
privKey := crypto.GenPrivKeyEd25519FromSecret([]byte(secret))
return privKey.Wrap()
}

func secret(index int) []byte {
return []byte(fmt.Sprintf("secret%d", index))
func secret(index int) string {
return fmt.Sprintf("secret%d", index)
}

func copyVal(val *abci.Validator) *abci.Validator {
val2 := *val
return &val2
func copyVal(val abci.Validator) abci.Validator {
// val2 := *val
// return &val2
return val
}

func toJSON(o interface{}) []byte {
bytes, err := json.Marshal(o)
bz, err := json.Marshal(o)
if err != nil {
panic(err)
}
return bytes
// fmt.Println(">> toJSON:", string(bz))
return bz
}

func fromJSON(bytes []byte, ptr interface{}) {
err := json.Unmarshal(bytes, ptr)
func fromJSON(bz []byte, ptr interface{}) {
// fmt.Println(">> fromJSON:", string(bz))
err := json.Unmarshal(bz, ptr)
if err != nil {
panic(err)
}
}

// Creates a sample CommitMultiStore
func newCommitMultiStore() types.CommitMultiStore {
dbMain := dbm.NewMemDB()
dbXtra := dbm.NewMemDB()
ms := store.NewMultiStore(dbMain) // Also store rootMultiStore metadata here (it shouldn't clash)
ms.SetSubstoreLoader("main", store.NewIAVLStoreLoader(dbMain, 0, 0))
ms.SetSubstoreLoader("xtra", store.NewIAVLStoreLoader(dbXtra, 0, 0))
return ms
}
54 changes: 54 additions & 0 deletions app/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package app

/*
XXX Make this work with MultiStore.
XXX It will require some interfaces updates in store/types.go.
if len(reqQuery.Data) == 0 {
resQuery.Log = "Query cannot be zero length"
resQuery.Code = abci.CodeType_EncodingError
return
}
// set the query response height to current
tree := app.state.Committed()
height := reqQuery.Height
if height == 0 {
// TODO: once the rpc actually passes in non-zero
// heights we can use to query right after a tx
// we must retrun most recent, even if apphash
// is not yet in the blockchain
withProof := app.CommittedHeight() - 1
if tree.Tree.VersionExists(withProof) {
height = withProof
} else {
height = app.CommittedHeight()
}
}
resQuery.Height = height
switch reqQuery.Path {
case "/store", "/key": // Get by key
key := reqQuery.Data // Data holds the key bytes
resQuery.Key = key
if reqQuery.Prove {
value, proof, err := tree.GetVersionedWithProof(key, height)
if err != nil {
resQuery.Log = err.Error()
break
}
resQuery.Value = value
resQuery.Proof = proof.Bytes()
} else {
value := tree.Get(key)
resQuery.Value = value
}
default:
resQuery.Code = abci.CodeType_UnknownRequest
resQuery.Log = cmn.Fmt("Unexpected Query path: %v", reqQuery.Path)
}
return
*/
4 changes: 2 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion store/iavlstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type iavlStore struct {
tree *iavl.VersionedTree

// How many old versions we hold onto.
// A value of 0 means keep all history.
numHistory int64
}

Expand All @@ -71,7 +72,7 @@ func (st *iavlStore) Commit() CommitID {
}

// Release an old version of history
if st.numHistory < st.tree.Version64() {
if st.numHistory > 0 && (st.numHistory < st.tree.Version64()) {
toRelease := version - st.numHistory
st.tree.DeleteVersion(toRelease)
}
Expand Down
45 changes: 31 additions & 14 deletions store/rootmultistore.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type rootMultiStore struct {
substores map[string]CommitStore
}

var _ CommitMultiStore = (*rootMultiStore)(nil)

func NewMultiStore(db dbm.DB) *rootMultiStore {
return &rootMultiStore{
db: db,
Expand All @@ -35,24 +37,26 @@ func NewMultiStore(db dbm.DB) *rootMultiStore {
}
}

// Implements CommitMultiStore.
func (rs *rootMultiStore) SetSubstoreLoader(name string, loader CommitStoreLoader) {
if _, ok := rs.storeLoaders[name]; ok {
panic(fmt.Sprintf("rootMultiStore duplicate substore name " + name))
}
rs.storeLoaders[name] = loader
}

// Call once after all calls to SetSubstoreLoader are complete.
// Implements CommitMultiStore.
func (rs *rootMultiStore) GetSubstore(name string) CommitStore {
return rs.substores[name]
}

// Implements CommitMultiStore.
func (rs *rootMultiStore) LoadLatestVersion() error {
ver := getLatestVersion(rs.db)
return rs.LoadVersion(ver)
}

// NOTE: Returns 0 unless LoadVersion() or LoadLatestVersion() is called.
func (rs *rootMultiStore) NextVersion() int64 {
return rs.nextVersion
}

// Implements CommitMultiStore.
func (rs *rootMultiStore) LoadVersion(ver int64) error {

// Special logic for version 0
Expand Down Expand Up @@ -106,10 +110,13 @@ func (rs *rootMultiStore) LoadVersion(ver int64) error {
return nil
}

// Implements CommitStore
//----------------------------------------
// +CommitStore

// Implements CommitStore.
func (rs *rootMultiStore) Commit() CommitID {

// Commit substores
// Commit substores.
version := rs.nextVersion
state := commitSubstores(version, rs.substores)

Expand All @@ -129,27 +136,36 @@ func (rs *rootMultiStore) Commit() CommitID {
return commitID
}

// Implements CommitStore
// Implements CommitStore.
func (rs *rootMultiStore) CacheWrap() CacheWrap {
return rs.CacheMultiStore().(CacheWrap)
}

// Get the last committed CommitID
//----------------------------------------
// +MultiStore

// Implements MultiStore.
func (rs *rootMultiStore) LastCommitID() CommitID {
return rs.lastCommitID
}

// Implements MultiStore
// Implements MultiStore.
// NOTE: Returns 0 unless LoadVersion() or LoadLatestVersion() is called.
func (rs *rootMultiStore) NextVersion() int64 {
return rs.nextVersion
}

// Implements MultiStore.
func (rs *rootMultiStore) CacheMultiStore() CacheMultiStore {
return newCacheMultiStoreFromRMS(rs)
}

// Implements MultiStore
func (rs *rootMultiStore) GetCommitStore(name string) CommitStore {
// Implements MultiStore.
func (rs *rootMultiStore) GetStore(name string) interface{} {
return rs.substores[name]
}

// Implements MultiStore
// Implements MultiStore.
func (rs *rootMultiStore) GetKVStore(name string) KVStore {
return rs.substores[name].(KVStore)
}
Expand Down Expand Up @@ -208,6 +224,7 @@ func (sc substoreCore) Hash() []byte {
}

//----------------------------------------
// Misc.

func getLatestVersion(db dbm.DB) int64 {
var latest int64
Expand Down
13 changes: 9 additions & 4 deletions x/coin/coin.go → types/coin.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package coin
package types

import (
"fmt"
"sort"
"strconv"
"strings"

"github.com/pkg/errors"
)

// Coin hold some amount of one currency
Expand Down Expand Up @@ -200,3 +197,11 @@ var _ sort.Interface = Coins{}

// Sort is a helper function to sort the set of coins inplace
func (coins Coins) Sort() { sort.Sort(coins) }

//----------------------------------------
// Misc

type Coinser interface {
GetCoins() Coins
SetCoins(Coins)
}
2 changes: 1 addition & 1 deletion x/coin/coin_test.go → types/coin_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package coin
package types

import (
"testing"
Expand Down
Loading