Skip to content

Commit

Permalink
Plugins and AccountCaches
Browse files Browse the repository at this point in the history
  • Loading branch information
jaekwon committed Mar 24, 2016
1 parent 83e7c9d commit 964a4cf
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 22 deletions.
4 changes: 3 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ type Basecoin struct {
}

func NewBasecoin(eyesCli *eyes.Client) *Basecoin {
state_ := state.NewState(eyesCli)
govMint := gov.NewGovernmint(eyesCli)
state_.RegisterPlugin([]byte("gov"), govMint)
return &Basecoin{
eyesCli: eyesCli,
govMint: govMint,
state: state.NewState(eyesCli),
state: state_,
}
}

Expand Down
46 changes: 46 additions & 0 deletions state/account_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package state

import (
"github.com/tendermint/basecoin/types"
"sort"
)

type AccountCache struct {
state *State
accounts map[string]*types.Account
}

func NewAccountCache(state *State) *AccountCache {
return &AccountCache{
state: state,
accounts: make(map[string]*types.Account),
}
}

func (cache *AccountCache) GetAccount(addr []byte) *types.Account {
acc, ok := cache.accounts[string(addr)]
if !ok {
acc = cache.state.GetAccount(addr)
cache.accounts[string(addr)] = acc
}
return acc
}

func (cache *AccountCache) SetAccount(addr []byte, acc *types.Account) {
cache.accounts[string(addr)] = acc
}

func (cache *AccountCache) Sync() {
// MUST BE DETERMINISTIC
// First, order the addrs.
addrs := []string{}
for addr := range cache.accounts {
addrs = append(addrs, string(addr))
}
sort.Strings(addrs)

// Set the accounts in order.
for _, addr := range addrs {
cache.state.SetAccount([]byte(addr), cache.accounts[addr])
}
}
36 changes: 22 additions & 14 deletions state/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package state

import (
"bytes"
"strings"

"github.com/tendermint/basecoin/types"
. "github.com/tendermint/go-common"
Expand Down Expand Up @@ -94,9 +93,8 @@ func ExecTx(state *State, tx types.Tx, isCheckTx bool, evc events.Fireable) tmsp
}

// Validate call address
if strings.HasPrefix(string(tx.Address), "gov/") {
// This is a gov call.
} else {
plugin := state.GetPlugin(tx.Address)
if plugin != nil {
return tmsp.ErrBaseUnknownAddress.AppendLog(Fmt("Unrecognized address %X", tx.Address))
}

Expand All @@ -105,16 +103,21 @@ func ExecTx(state *State, tx types.Tx, isCheckTx bool, evc events.Fireable) tmsp
inAcc.Sequence += 1
inAcc.Balance -= tx.Input.Amount
state.SetCheckAccount(tx.Input.Address, inAcc.Sequence, inAcc.Balance)
inAccCopy := inAcc.Copy()

// If this is AppendTx, actually save accounts
if !isCheckTx {
state.SetAccount(tx.Input.Address, inAcc)
// NOTE: value is dangling.
// XXX: don't just give it back
inAcc.Balance += value
// TODO: logic.
// TODO: persist
// state.SetAccount(tx.Input.Address, inAcc)
if isCheckTx {
return tmsp.OK
}

// Run the tx.
cache := NewAccountCache(state)
cache.SetAccount(tx.Input.Address, inAcc)
gas := int64(1) // TODO
ctx := types.NewCallContext(cache, inAcc, value, &gas)
res = plugin.CallTx(ctx, tx.Data)
if res.IsOK() {
cache.Sync()
log.Info("Successful execution")
// Fire events
/*
Expand All @@ -127,9 +130,14 @@ func ExecTx(state *State, tx types.Tx, isCheckTx bool, evc events.Fireable) tmsp
evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventDataTx{tx, ret, exception})
}
*/
} else {
log.Info("CallTx failed", "error", res)
// Just return the value and return.
// TODO: return gas?
inAccCopy.Balance += value
state.SetAccount(tx.Input.Address, inAccCopy)
}

return tmsp.OK
return res

default:
return tmsp.ErrBaseEncodingError.SetLog("Unknown tx type")
Expand Down
9 changes: 9 additions & 0 deletions state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type State struct {
chainID string
eyesCli *eyes.Client
checkCache map[string]checkAccount
plugins map[string]types.Plugin

LastBlockHeight uint64
LastBlockHash []byte
Expand All @@ -37,6 +38,14 @@ 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) GetPlugin(addr []byte) types.Plugin {
return s.plugins[string(addr)]
}

//----------------------------------------
// CheckTx state

Expand Down
8 changes: 7 additions & 1 deletion types/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ type AccountGetter interface {

type AccountGetterSetter interface {
GetAccount(addr []byte) *Account
SetAccount(acc *Account)
SetAccount(addr []byte, acc *Account)
}

type AccountCacher interface {
GetAccount(addr []byte) *Account
SetAccount(addr []byte, acc *Account)
Sync()
}
6 changes: 0 additions & 6 deletions types/native.go

This file was deleted.

28 changes: 28 additions & 0 deletions types/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package types

import (
tmsp "github.com/tendermint/tmsp/types"
)

// Value is any floating value. It must be given to someone.
// 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
}

type CallContext struct {
Cache AccountCacher
Caller *Account
Value int64
Gas *int64
}

func NewCallContext(cache AccountCacher, caller *Account, value int64, gas *int64) CallContext {
return CallContext{
Cache: cache,
Caller: caller,
Value: value,
Gas: gas,
}
}

0 comments on commit 964a4cf

Please sign in to comment.