Plugin support for SetOption, Query, and Commit
This commit is contained in:
parent
964a4cfd50
commit
601a654b7d
88
app/app.go
88
app/app.go
|
@ -1,6 +1,8 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/basecoin/state"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
. "github.com/tendermint/go-common"
|
||||
|
@ -22,7 +24,7 @@ type Basecoin struct {
|
|||
func NewBasecoin(eyesCli *eyes.Client) *Basecoin {
|
||||
state_ := state.NewState(eyesCli)
|
||||
govMint := gov.NewGovernmint(eyesCli)
|
||||
state_.RegisterPlugin([]byte("gov"), govMint)
|
||||
state_.RegisterPlugin("GOV", govMint)
|
||||
return &Basecoin{
|
||||
eyesCli: eyesCli,
|
||||
govMint: govMint,
|
||||
|
@ -37,25 +39,37 @@ func (app *Basecoin) Info() string {
|
|||
|
||||
// TMSP::SetOption
|
||||
func (app *Basecoin) SetOption(key string, value string) (log string) {
|
||||
switch key {
|
||||
case "chainID":
|
||||
app.state.SetChainID(value)
|
||||
return "Success"
|
||||
case "account":
|
||||
var err error
|
||||
var setAccount types.Account
|
||||
wire.ReadJSONPtr(&setAccount, []byte(value), &err)
|
||||
if err != nil {
|
||||
return "Error decoding setAccount message: " + err.Error()
|
||||
|
||||
pluginName, key := splitKey(key)
|
||||
if pluginName != "BASE" {
|
||||
// Set option on plugin
|
||||
plugin := app.state.GetPlugin(pluginName)
|
||||
if plugin == nil {
|
||||
return "Invalid plugin name: " + pluginName
|
||||
}
|
||||
accBytes := wire.BinaryBytes(setAccount)
|
||||
res := app.eyesCli.SetSync(setAccount.PubKey.Address(), accBytes)
|
||||
if res.IsErr() {
|
||||
return "Error saving account: " + res.Error()
|
||||
return plugin.SetOption(key, value)
|
||||
} else {
|
||||
// Set option on basecoin
|
||||
switch key {
|
||||
case "chainID":
|
||||
app.state.SetChainID(value)
|
||||
return "Success"
|
||||
case "account":
|
||||
var err error
|
||||
var setAccount types.Account
|
||||
wire.ReadJSONPtr(&setAccount, []byte(value), &err)
|
||||
if err != nil {
|
||||
return "Error decoding setAccount message: " + err.Error()
|
||||
}
|
||||
accBytes := wire.BinaryBytes(setAccount)
|
||||
res := app.eyesCli.SetSync(setAccount.PubKey.Address(), accBytes)
|
||||
if res.IsErr() {
|
||||
return "Error saving account: " + res.Error()
|
||||
}
|
||||
return "Success"
|
||||
}
|
||||
return "Success"
|
||||
return "Unrecognized option key " + key
|
||||
}
|
||||
return "Unrecognized option key " + key
|
||||
}
|
||||
|
||||
// TMSP::AppendTx
|
||||
|
@ -98,18 +112,36 @@ func (app *Basecoin) CheckTx(txBytes []byte) (res tmsp.Result) {
|
|||
|
||||
// TMSP::Query
|
||||
func (app *Basecoin) Query(query []byte) (res tmsp.Result) {
|
||||
res = app.eyesCli.GetSync(query)
|
||||
if res.IsErr() {
|
||||
return res.PrependLog("Error querying eyesCli")
|
||||
pluginName, queryStr := splitKey(string(query))
|
||||
if pluginName != "BASE" {
|
||||
plugin := app.state.GetPlugin(pluginName)
|
||||
if plugin == nil {
|
||||
return tmsp.ErrBaseUnknownPlugin.SetLog(Fmt("Unknown plugin %v", pluginName))
|
||||
}
|
||||
return plugin.Query([]byte(queryStr))
|
||||
} else {
|
||||
// TODO turn Basecoin ops into a plugin?
|
||||
res = app.eyesCli.GetSync([]byte(queryStr))
|
||||
if res.IsErr() {
|
||||
return res.PrependLog("Error querying eyesCli")
|
||||
}
|
||||
return res
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// TMSP::Commit
|
||||
func (app *Basecoin) Commit() (res tmsp.Result) {
|
||||
// First, commit all the plugins
|
||||
for _, plugin := range app.state.GetPlugins() {
|
||||
res = plugin.Commit()
|
||||
if res.IsErr() {
|
||||
PanicSanity(Fmt("Error committing plugin %v", plugin.Name))
|
||||
}
|
||||
}
|
||||
// Then, commit eyes.
|
||||
res = app.eyesCli.CommitSync()
|
||||
if res.IsErr() {
|
||||
panic("Error getting hash: " + res.Error())
|
||||
PanicSanity("Error getting hash: " + res.Error())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -124,3 +156,15 @@ func (app *Basecoin) EndBlock(height uint64) []*tmsp.Validator {
|
|||
app.state.ResetCacheState()
|
||||
return app.govMint.EndBlock(height)
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
// Splits the string at the first :.
|
||||
// if there are none, the second string is nil.
|
||||
func splitKey(key string) (prefix string, sufix string) {
|
||||
if strings.Contains(key, ":") {
|
||||
keyParts := strings.SplitN(key, ":", 2)
|
||||
return keyParts[0], keyParts[1]
|
||||
}
|
||||
return key, ""
|
||||
}
|
||||
|
|
|
@ -93,9 +93,9 @@ func ExecTx(state *State, tx types.Tx, isCheckTx bool, evc events.Fireable) tmsp
|
|||
}
|
||||
|
||||
// Validate call address
|
||||
plugin := state.GetPlugin(tx.Address)
|
||||
plugin := state.GetPlugin(string(tx.Address))
|
||||
if plugin != nil {
|
||||
return tmsp.ErrBaseUnknownAddress.AppendLog(Fmt("Unrecognized address %X", tx.Address))
|
||||
return tmsp.ErrBaseUnknownAddress.AppendLog(Fmt("Unrecognized address %X (%v)", tx.Address, string(tx.Address)))
|
||||
}
|
||||
|
||||
// Good!
|
||||
|
|
|
@ -8,10 +8,11 @@ import (
|
|||
)
|
||||
|
||||
type State struct {
|
||||
chainID string
|
||||
eyesCli *eyes.Client
|
||||
checkCache map[string]checkAccount
|
||||
plugins map[string]types.Plugin
|
||||
chainID string
|
||||
eyesCli *eyes.Client
|
||||
checkCache map[string]checkAccount
|
||||
plugins map[string]types.Plugin
|
||||
pluginsList []types.NamedPlugin
|
||||
|
||||
LastBlockHeight uint64
|
||||
LastBlockHash []byte
|
||||
|
@ -23,6 +24,7 @@ func NewState(eyesCli *eyes.Client) *State {
|
|||
chainID: "",
|
||||
eyesCli: eyesCli,
|
||||
checkCache: make(map[string]checkAccount),
|
||||
plugins: make(map[string]types.Plugin),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -38,12 +40,20 @@ func (s *State) GetChainID() string {
|
|||
return s.chainID
|
||||
}
|
||||
|
||||
func (s *State) RegisterPlugin(addr []byte, plugin types.Plugin) {
|
||||
s.plugins[string(addr)] = plugin
|
||||
func (s *State) RegisterPlugin(name string, plugin types.Plugin) {
|
||||
s.plugins[name] = plugin
|
||||
s.pluginsList = append(s.pluginsList, types.NamedPlugin{
|
||||
Name: name,
|
||||
Plugin: plugin,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *State) GetPlugin(addr []byte) types.Plugin {
|
||||
return s.plugins[string(addr)]
|
||||
func (s *State) GetPlugin(name string) types.Plugin {
|
||||
return s.plugins[name]
|
||||
}
|
||||
|
||||
func (s *State) GetPlugins() []types.NamedPlugin {
|
||||
return s.pluginsList
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
|
|
@ -8,17 +8,16 @@ import (
|
|||
"github.com/tendermint/basecoin/types"
|
||||
. "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-wire"
|
||||
govtypes "github.com/tendermint/governmint/types"
|
||||
eyescli "github.com/tendermint/merkleeyes/client"
|
||||
_ "github.com/tendermint/tendermint/rpc/core/types" // Register RPCResponse > Result types
|
||||
)
|
||||
|
||||
/*
|
||||
Get the "test" account.
|
||||
PrivKey: 019F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A0867D3B5EAF0C0BF6B5A602D359DAECC86A7A74053490EC37AE08E71360587C870
|
||||
PubKey: 0167D3B5EAF0C0BF6B5A602D359DAECC86A7A74053490EC37AE08E71360587C870
|
||||
Address: D9B727742AA29FA638DC63D70813C976014C4CE0
|
||||
*/
|
||||
func main() {
|
||||
//testSendTx()
|
||||
testGov()
|
||||
}
|
||||
|
||||
func testSendTx() {
|
||||
eyesCli := eyescli.NewLocalClient()
|
||||
bcApp := app.NewBasecoin(eyesCli)
|
||||
fmt.Println(bcApp.Info())
|
||||
|
@ -61,4 +60,27 @@ func main() {
|
|||
txBytes := wire.BinaryBytes(tx)
|
||||
res := bcApp.AppendTx(txBytes)
|
||||
fmt.Println(res)
|
||||
if res.IsErr() {
|
||||
Exit(Fmt("Failed: %v", res.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func testGov() {
|
||||
eyesCli := eyescli.NewLocalClient()
|
||||
bcApp := app.NewBasecoin(eyesCli)
|
||||
fmt.Println(bcApp.Info())
|
||||
|
||||
tPriv := tests.PrivAccountFromSecret("test")
|
||||
|
||||
// Seed Basecoin with admin using PrivAccount
|
||||
tAcc := tPriv.Account
|
||||
adminEntity := govtypes.Entity{
|
||||
ID: "",
|
||||
PubKey: tAcc.PubKey,
|
||||
}
|
||||
log := bcApp.SetOption("GOV:admin", string(wire.JSONBytes(adminEntity)))
|
||||
if log != "Success" {
|
||||
Exit(Fmt("Failed to set option: %v", log))
|
||||
}
|
||||
// TODO test proposals or something.
|
||||
}
|
||||
|
|
|
@ -8,7 +8,15 @@ import (
|
|||
// Gas is a pointer to remainig gas. Decrement as you go,
|
||||
// if any gas is left the user is
|
||||
type Plugin interface {
|
||||
CallTx(ctx CallContext, txBytes []byte) tmsp.Result
|
||||
SetOption(key string, value string) (log string)
|
||||
CallTx(ctx CallContext, txBytes []byte) (res tmsp.Result)
|
||||
Query(query []byte) (res tmsp.Result)
|
||||
Commit() (res tmsp.Result)
|
||||
}
|
||||
|
||||
type NamedPlugin struct {
|
||||
Name string
|
||||
Plugin
|
||||
}
|
||||
|
||||
type CallContext struct {
|
||||
|
|
Loading…
Reference in New Issue