parent
fdc7316fda
commit
14a0dce920
|
@ -261,6 +261,8 @@ func (app *App) runTx(isCheckTx bool, txBytes []byte) (result sdk.Result) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: override default ante handler w/ custom ante handler.
|
||||||
|
|
||||||
// Run the ante handler.
|
// Run the ante handler.
|
||||||
ctx, result, abort := app.defaultAnteHandler(ctx, tx)
|
ctx, result, abort := app.defaultAnteHandler(ctx, tx)
|
||||||
if isCheckTx || abort {
|
if isCheckTx || abort {
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
apm "github.com/cosmos/cosmos-sdk/app"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/tendermint/abci/server"
|
||||||
|
"github.com/tendermint/go-wire"
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
const appName = "BasecoinApp"
|
||||||
|
|
||||||
|
type BasecoinApp struct {
|
||||||
|
*apm.App
|
||||||
|
cdc *wire.Codec
|
||||||
|
multiStore sdk.CommitMultiStore
|
||||||
|
|
||||||
|
// The key to access the substores.
|
||||||
|
mainStoreKey *sdk.KVStoreKey
|
||||||
|
ibcStoreKey *sdk.KVStoreKey
|
||||||
|
|
||||||
|
// Additional stores:
|
||||||
|
accStore sdk.AccountStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This should take in more configuration options.
|
||||||
|
func NewBasecoinApp() *BasecoinApp {
|
||||||
|
|
||||||
|
// Create and configure app.
|
||||||
|
var app = &BasecoinApp{}
|
||||||
|
app.initKeys()
|
||||||
|
app.initMultiStore()
|
||||||
|
app.initAppStore()
|
||||||
|
app.initSDKApp()
|
||||||
|
app.initCodec()
|
||||||
|
app.initTxDecoder()
|
||||||
|
app.initAnteHandler()
|
||||||
|
app.initRoutes()
|
||||||
|
|
||||||
|
// TODO: Load genesis
|
||||||
|
// TODO: InitChain with validators
|
||||||
|
// TODO: Set the genesis accounts
|
||||||
|
app.loadStores()
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *BasecoinApp) RunForever() {
|
||||||
|
|
||||||
|
// Start the ABCI server
|
||||||
|
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
srv.Start()
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
cmn.TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
srv.Stop()
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *BasecoinApp) initKeys() {
|
||||||
|
app.mainStoreKey = sdk.NewKVStoreKey("main")
|
||||||
|
app.ibcStoreKey = sdk.NewKVStoreKey("ibc")
|
||||||
|
}
|
||||||
|
|
||||||
|
// depends on initMultiStore()
|
||||||
|
func (app *BasecoinApp) initSDKApp() {
|
||||||
|
app.App = apm.NewApp(appName, app.multiStore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *BasecoinApp) initCodec() {
|
||||||
|
app.cdc = wire.NewCodec()
|
||||||
|
}
|
||||||
|
|
||||||
|
// depends on initSDKApp()
|
||||||
|
func (app *BasecoinApp) initTxDecoder() {
|
||||||
|
app.App.SetTxDecoder(app.decodeTx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// initAnteHandler defined in app/routes.go
|
||||||
|
// initRoutes defined in app/routes.go
|
||||||
|
|
||||||
|
// Load the stores.
|
||||||
|
func (app *BasecoinApp) loadStores() {
|
||||||
|
if err := app.LoadLatestVersion(app.mainStoreKey); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set via `app.App.SetTxDecoder(app.decodeTx)`
|
||||||
|
func (app *BasecoinApp) decodeTx(txBytes []byte) (sdk.Tx, error) {
|
||||||
|
var tx = sdk.StdTx{}
|
||||||
|
err := app.cdc.UnmarshalBinary(txBytes, &tx)
|
||||||
|
return tx, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wire requires registration of interfaces & concrete types.
|
||||||
|
func (app *BasecoinApp) registerMsgs() {
|
||||||
|
cdc := app.cdc
|
||||||
|
|
||||||
|
// Register the Msg interface.
|
||||||
|
cdc.RegisterInterface((*sdk.Msg)(nil), nil)
|
||||||
|
cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil) // XXX refactor out
|
||||||
|
cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil) // XXX refactor out to bank/msgs.go
|
||||||
|
// more msgs here...
|
||||||
|
|
||||||
|
// All interfaces to be encoded/decoded in a Msg must be
|
||||||
|
// registered here, along with all the concrete types that
|
||||||
|
// implement them.
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handle charging tx fees and checking signatures.
|
||||||
|
func (app *BasecoinApp) initAnteHandler() {
|
||||||
|
var authAnteHandler = auth.NewAnteHandler(app.accStore)
|
||||||
|
app.App.SetDefaultAnteHandler(authAnteHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs router to route handling of msgs.
|
||||||
|
func (app *BasecoinApp) initRoutes() {
|
||||||
|
var router = app.App.Router()
|
||||||
|
// var multiStore = app.multiStore
|
||||||
|
var accStore = app.accStore
|
||||||
|
|
||||||
|
router.AddRoute("bank", bank.NewHandler(accStore))
|
||||||
|
// more routes here... (order matters)
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/store"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// depends on initKeys()
|
||||||
|
func (app *BasecoinApp) initMultiStore() {
|
||||||
|
|
||||||
|
// Create the underlying leveldb datastore which will
|
||||||
|
// persist the Merkle tree inner & leaf nodes.
|
||||||
|
db, err := dbm.NewGoLevelDB("basecoin", "basecoin-data")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create CommitStoreLoader.
|
||||||
|
cacheSize := 10000
|
||||||
|
numHistory := int64(100)
|
||||||
|
mainLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
||||||
|
ibcLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
||||||
|
|
||||||
|
// Create MultiStore
|
||||||
|
multiStore := store.NewCommitMultiStore(db)
|
||||||
|
multiStore.SetSubstoreLoader(app.mainStoreKey, mainLoader)
|
||||||
|
multiStore.SetSubstoreLoader(app.ibcStoreKey, ibcLoader)
|
||||||
|
|
||||||
|
// Finally,
|
||||||
|
app.multiStore = multiStore
|
||||||
|
}
|
||||||
|
|
||||||
|
// depends on initKeys()
|
||||||
|
func (app *BasecoinApp) initAppStore() {
|
||||||
|
app.accStore = auth.NewAccountStore(
|
||||||
|
app.mainStoreKey,
|
||||||
|
types.AppAccountCodec{},
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,99 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/app"
|
|
||||||
"github.com/cosmos/cosmos-sdk/store"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
|
||||||
"github.com/tendermint/abci/server"
|
|
||||||
"github.com/tendermint/go-wire"
|
|
||||||
cmn "github.com/tendermint/tmlibs/common"
|
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
|
||||||
|
|
||||||
bcm "github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// Create the underlying leveldb datastore which will
|
|
||||||
// persist the Merkle tree inner & leaf nodes.
|
|
||||||
db, err := dbm.NewGoLevelDB("basecoin", "basecoin-data")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create CommitStoreLoader.
|
|
||||||
cacheSize := 10000
|
|
||||||
numHistory := int64(100)
|
|
||||||
mainLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
|
||||||
ibcLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
|
|
||||||
|
|
||||||
// The key to access the main KVStore.
|
|
||||||
var mainStoreKey = sdk.NewKVStoreKey("main")
|
|
||||||
var ibcStoreKey = sdk.NewKVStoreKey("ibc")
|
|
||||||
|
|
||||||
// Create MultiStore
|
|
||||||
multiStore := store.NewCommitMultiStore(db)
|
|
||||||
multiStore.SetSubstoreLoader(mainStoreKey, mainLoader)
|
|
||||||
multiStore.SetSubstoreLoader(ibcStoreKey, ibcLoader)
|
|
||||||
|
|
||||||
// Create the Application.
|
|
||||||
app := app.NewApp("basecoin", multiStore)
|
|
||||||
|
|
||||||
// Set Tx decoder
|
|
||||||
app.SetTxDecoder(decodeTx)
|
|
||||||
|
|
||||||
var accStore = auth.NewAccountStore(mainStoreKey, bcm.AppAccountCodec{})
|
|
||||||
var authAnteHandler = auth.NewAnteHandler(accStore)
|
|
||||||
|
|
||||||
// Handle charging fees and checking signatures.
|
|
||||||
app.SetDefaultAnteHandler(authAnteHandler)
|
|
||||||
|
|
||||||
// Add routes to App.
|
|
||||||
app.Router().AddRoute("bank", bank.NewHandler(accStore))
|
|
||||||
|
|
||||||
// TODO: load genesis
|
|
||||||
// TODO: InitChain with validators
|
|
||||||
// accounts := auth.NewAccountStore(multiStore.GetKVStore("main"))
|
|
||||||
// TODO: set the genesis accounts
|
|
||||||
|
|
||||||
// Load the stores.
|
|
||||||
if err := app.LoadLatestVersion(mainStoreKey); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the ABCI server
|
|
||||||
srv, err := server.NewServer("0.0.0.0:46658", "socket", app)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
srv.Start()
|
|
||||||
|
|
||||||
// Wait forever
|
|
||||||
cmn.TrapSignal(func() {
|
|
||||||
// Cleanup
|
|
||||||
srv.Stop()
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------
|
|
||||||
// Misc.
|
|
||||||
|
|
||||||
func registerMsgs() {
|
|
||||||
wire.RegisterInterface((*sdk.Msg)(nil), nil)
|
|
||||||
wire.RegisterConcrete(&bank.SendMsg{}, "com.cosmos.basecoin.send_msg", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeTx(txBytes []byte) (sdk.Tx, error) {
|
|
||||||
var tx = sdk.StdTx{}
|
|
||||||
err := wire.UnmarshalBinary(txBytes, &tx)
|
|
||||||
return tx, err
|
|
||||||
}
|
|
|
@ -39,6 +39,9 @@ func NewCommitMultiStore(db dbm.DB) *rootMultiStore {
|
||||||
|
|
||||||
// Implements CommitMultiStore.
|
// Implements CommitMultiStore.
|
||||||
func (rs *rootMultiStore) SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) {
|
func (rs *rootMultiStore) SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader) {
|
||||||
|
if key == nil {
|
||||||
|
panic("SetSubstoreLoader() key cannot be nil")
|
||||||
|
}
|
||||||
if _, ok := rs.storeLoaders[key]; ok {
|
if _, ok := rs.storeLoaders[key]; ok {
|
||||||
panic(fmt.Sprintf("rootMultiStore duplicate substore key", key))
|
panic(fmt.Sprintf("rootMultiStore duplicate substore key", key))
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,11 @@ type CommitMultiStore interface {
|
||||||
MultiStore
|
MultiStore
|
||||||
|
|
||||||
// Add a substore loader.
|
// Add a substore loader.
|
||||||
|
// Panics on a nil key.
|
||||||
SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader)
|
SetSubstoreLoader(key SubstoreKey, loader CommitStoreLoader)
|
||||||
|
|
||||||
// Gets the substore, which is a CommitSubstore.
|
// Gets the substore, which is a CommitSubstore.
|
||||||
|
// Panics on a nil key.
|
||||||
GetSubstore(key SubstoreKey) CommitStore
|
GetSubstore(key SubstoreKey) CommitStore
|
||||||
|
|
||||||
// Load the latest persisted version.
|
// Load the latest persisted version.
|
||||||
|
|
|
@ -55,7 +55,7 @@ func NewAnteHandler(store sdk.AccountStore) sdk.AnteHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and incremenet sequence number.
|
// Check and increment sequence number.
|
||||||
seq := signerAcc.GetSequence()
|
seq := signerAcc.GetSequence()
|
||||||
if seq != sig.Sequence {
|
if seq != sig.Sequence {
|
||||||
return ctx, sdk.Result{
|
return ctx, sdk.Result{
|
||||||
|
|
|
@ -2,38 +2,56 @@ package bank
|
||||||
|
|
||||||
import (
|
import (
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Handle all "bank" type messages.
|
||||||
func NewHandler(accStore sdk.AccountStore) sdk.Handler {
|
func NewHandler(accStore sdk.AccountStore) sdk.Handler {
|
||||||
|
|
||||||
return func(ctx sdk.Context, tx sdk.Tx) sdk.Result {
|
return func(ctx sdk.Context, tx sdk.Tx) sdk.Result {
|
||||||
cs := CoinStore{accStore}
|
cs := CoinStore{accStore}
|
||||||
|
msg := tx.(sdk.Msg)
|
||||||
sendTx, ok := tx.(sdk.Msg).(SendMsg)
|
switch msg := msg.(type) {
|
||||||
if !ok {
|
case SendMsg:
|
||||||
panic("tx is not SendTx") // ?
|
return handleSendMsg(ctx, cs, msg)
|
||||||
}
|
case IssueMsg:
|
||||||
|
return handleIssueMsg(ctx, cs, msg)
|
||||||
// NOTE: totalIn == totalOut should already have been checked
|
default:
|
||||||
|
return sdk.Result{
|
||||||
for _, in := range sendTx.Inputs {
|
Code: 1, // TODO
|
||||||
_, err := cs.SubtractCoins(ctx, in.Address, in.Coins)
|
Log: "Unrecognized bank Tx type: " + reflect.TypeOf(tx).Name(),
|
||||||
if err != nil {
|
|
||||||
return sdk.Result{
|
|
||||||
Code: 1, // TODO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, out := range sendTx.Outputs {
|
|
||||||
_, err := cs.AddCoins(ctx, out.Address, out.Coins)
|
|
||||||
if err != nil {
|
|
||||||
return sdk.Result{
|
|
||||||
Code: 1, // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sdk.Result{} // TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle SendMsg.
|
||||||
|
func handleSendMsg(ctx sdk.Context, cs CoinStore, msg SendMsg) sdk.Result {
|
||||||
|
// NOTE: totalIn == totalOut should already have been checked
|
||||||
|
|
||||||
|
for _, in := range msg.Inputs {
|
||||||
|
_, err := cs.SubtractCoins(ctx, in.Address, in.Coins)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Result{
|
||||||
|
Code: 1, // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, out := range msg.Outputs {
|
||||||
|
_, err := cs.AddCoins(ctx, out.Address, out.Coins)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Result{
|
||||||
|
Code: 1, // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sdk.Result{} // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle IssueMsg.
|
||||||
|
func handleIssueMsg(ctx sdk.Context, cs CoinStore, msg IssueMsg) sdk.Result {
|
||||||
|
panic("not implemented yet")
|
||||||
}
|
}
|
||||||
|
|
54
x/bank/tx.go
54
x/bank/tx.go
|
@ -81,6 +81,60 @@ func (msg SendMsg) GetSigners() []crypto.Address {
|
||||||
return addrs
|
return addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
// IssueMsg
|
||||||
|
|
||||||
|
// IssueMsg - high level transaction of the coin module
|
||||||
|
type IssueMsg struct {
|
||||||
|
Banker crypto.Address `json:"banker"`
|
||||||
|
Outputs []Output `json:"outputs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIssueMsg - construct arbitrary multi-in, multi-out send msg.
|
||||||
|
func NewIssueMsg(banker crypto.Address, out []Output) IssueMsg {
|
||||||
|
return IssueMsg{Banker: banker, Outputs: out}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Msg.
|
||||||
|
func (msg IssueMsg) Type() string { return "bank" } // TODO: "bank/send"
|
||||||
|
|
||||||
|
// Implements Msg.
|
||||||
|
func (msg IssueMsg) ValidateBasic() error {
|
||||||
|
// XXX
|
||||||
|
if len(msg.Outputs) == 0 {
|
||||||
|
return ErrNoOutputs()
|
||||||
|
}
|
||||||
|
for _, out := range msg.Outputs {
|
||||||
|
if err := out.ValidateBasic(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg IssueMsg) String() string {
|
||||||
|
return fmt.Sprintf("IssueMsg{%v#%v}", msg.Banker, msg.Outputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Msg.
|
||||||
|
func (msg IssueMsg) Get(key interface{}) (value interface{}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Msg.
|
||||||
|
func (msg IssueMsg) GetSignBytes() []byte {
|
||||||
|
b, err := json.Marshal(msg) // XXX: ensure some canonical form
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements Msg.
|
||||||
|
func (msg IssueMsg) GetSigners() []crypto.Address {
|
||||||
|
return []crypto.Address{msg.Banker}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Input
|
// Input
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue