Initial commit for permissioning...

This commit is contained in:
Jae Kwon 2018-01-10 20:11:44 -08:00
parent d3de10e22b
commit 51e6144c0d
24 changed files with 120 additions and 119 deletions

View File

@ -193,7 +193,7 @@ func (app *App) CheckTx(txBytes []byte) (res abci.ResponseCheckTx) {
}
// Run the handler.
var result = app.handler(ctx, app.ms, tx)
var result = app.handler(ctx, app.msCheck, tx)
// Tell the blockchain engine (i.e. Tendermint).
return abci.ResponseCheckTx{
@ -226,7 +226,7 @@ func (app *App) DeliverTx(txBytes []byte) (res abci.ResponseDeliverTx) {
}
// Run the handler.
var result = app.handler(ctx, app.ms, tx)
var result = app.handler(ctx, app.msDeliver, tx)
// After-handler hooks.
if result.Code == abci.CodeTypeOK {

View File

@ -30,20 +30,40 @@ func main() {
// create CommitStoreLoader
cacheSize := 10000
numHistory := int64(100)
loader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
mainLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
ibcLoader := store.NewIAVLStoreLoader(db, cacheSize, numHistory)
// The key to access the main KVStore.
var mainKey = storeKey("main")
var ibcKey = storeKey("ibc")
// Create MultiStore
multiStore := store.NewCommitMultiStore(db)
multiStore.SetSubstoreLoader("main", loader)
multiStore.SetSubstoreLoader(mainKey, mainLoader)
multiStore.SetSubstoreLoader(ibcKey, ibcLoader)
// XXX
var appAccountCodec AccountCodec = nil
// Create Handler
handler := types.ChainDecorators(
// recover.Decorator(),
// logger.Decorator(),
auth.DecoratorFn(acm.NewAccountStore),
).WithHandler(
coinstore.TransferHandlerFn(acm.NewAccountStore),
)
recover.Decorator(),
logger.Decorator(),
auth.Decorator(appAccountCodec),
fees.Decorator(mainKey),
rollbackDecorator(), // XXX define.
ibc.Decorator(ibcKey), // Handle IBC messages.
pos.Decorator(mainKey), // Handle staking messages.
gov.Decorator(mainKey), // Handle governance messages.
coins.Decorator(mainKey), // Handle coinstore messages.
).WithHandler(func(ctx types.context, tx Tx) Result {
/*
switch tx.(type) {
case CustomTx1: ...
case CustomTx2: ...
}
*/
})
// TODO: load genesis
// TODO: InitChain with validators
@ -75,10 +95,25 @@ func main() {
return
}
//----------------------------------------
// Misc.
func txParser(txBytes []byte) (types.Tx, error) {
var tx coinstore.SendTx
err := json.Unmarshal(txBytes, &tx)
return tx, err
}
//-----------------------------------------------------------------------------
// an unexported (private) key which no module could know of unless
// it was passed in from the app.
type storeKey struct {
writeable bool
name string
}
func newStoreKey(name string) storeKey {
return storeKey{true, name}
}
func (s storeKey) ReadOnly() storeKey {
return storeKey{false, s.name}
}

View File

@ -4,19 +4,12 @@ import (
crypto "github.com/tendermint/go-crypto"
)
// AccountStore indexes accounts by address.
type AccountStore interface {
NewAccountWithAddress(addr crypto.Address) Account
GetAccount(addr crypto.Address) Account
SetAccount(acc Account)
}
// Account is a standard account using a sequence number for replay protection
// and a pubkey for authentication.
type Account interface {
Address() crypto.Address
GetPubKey() crypto.PubKey
GetPubKey() crypto.PubKey // can return nil.
SetPubKey(crypto.PubKey) error
GetSequence() int64
@ -25,3 +18,10 @@ type Account interface {
Get(key interface{}) (value interface{}, err error)
Set(key interface{}, value interface{}) error
}
// AccountStore indexes accounts by address.
type AccountStore interface {
NewAccountWithAddress(addr crypto.Address) Account
GetAccount(addr crypto.Address) Account
SetAccount(acc Account)
}

View File

@ -1,4 +1,4 @@
package coin
package types
import (
"fmt"
@ -6,8 +6,6 @@ import (
"sort"
"strconv"
"strings"
"github.com/pkg/errors"
)
// Coin hold some amount of one currency
@ -220,7 +218,7 @@ func ParseCoin(coinStr string) (coin Coin, err error) {
matches := reCoin.FindStringSubmatch(coinStr)
if matches == nil {
err = errors.Errorf("Invalid coin expression: %s", coinStr)
err = fmt.Errorf("Invalid coin expression: %s", coinStr)
return
}
denomStr, amountStr := matches[2], matches[1]
@ -256,7 +254,7 @@ func ParseCoins(coinsStr string) (coins Coins, err error) {
// Validate coins before returning.
if !coins.IsValid() {
return nil, errors.Errorf("ParseCoins invalid: %#v", coins)
return nil, fmt.Errorf("ParseCoins invalid: %#v", coins)
}
return coins, nil

View File

@ -1,4 +1,4 @@
package coin
package types
import (
"testing"

View File

@ -34,7 +34,7 @@ func Decorator(ctx Context, ms MultiStore, tx Tx, next Handler) Result {
}
```
While well-written decorators wouldn't mutate any mutable context values, a malicious or buggy plugin can create unwanted side-effects, so it is highly advised for users of Context to only set immutable values. To help enforce this contract, we require values to be certain primitive types, or a Cloner.
While well-written decorators wouldn't mutate any mutable context values, a malicious or buggy plugin can create unwanted side-effects, so it is highly advised for users of Context to only set immutable values. To help enforce this contract, we require values to be certain primitive types, a Cloner, or a CacheWrapper.
*/
@ -60,6 +60,7 @@ func NewContext(header abci.Header, isCheckTx bool, txBytes []byte) Context {
func (c Context) Value(key interface{}) interface{} {
value := c.Context.Value(key)
// XXX Cachewrap? Probably not?
if cloner, ok := value.(Cloner); ok {
return cloner.Clone()
}
@ -69,34 +70,38 @@ func (c Context) Value(key interface{}) interface{} {
return value
}
func (c Context) WithValue(key interface{}, value Cloner) Context {
return c.withValue(key, value)
}
func (c Context) WithValueProto(key interface{}, value proto.Message) Context {
return c.withValue(key, value)
}
func (c Context) WithValueString(key interface{}, value string) Context {
return c.withValue(key, value)
}
func (c Context) WithValueInt32(key interface{}, value int32) Context {
return c.withValue(key, value)
}
func (c Context) WithValueUint32(key interface{}, value uint32) Context {
return c.withValue(key, value)
}
func (c Context) WithValueUint64(key interface{}, value uint64) Context {
return c.withValue(key, value)
}
func (c Context) WithValueUnsafe(key interface{}, value interface{}) Context {
return c.withValue(key, value)
}
func (c Context) WithCloner(key interface{}, value Cloner) Context {
return c.withValue(key, value)
}
func (c Context) WithCacheWrapper(key interface{}, value CacheWrapper) Context {
return c.withValue(key, value)
}
func (c Context) WithProtoMsg(key interface{}, value proto.Message) Context {
return c.withValue(key, value)
}
func (c Context) WithString(key interface{}, value string) Context {
return c.withValue(key, value)
}
func (c Context) WithInt32(key interface{}, value int32) Context {
return c.withValue(key, value)
}
func (c Context) WithUint32(key interface{}, value uint32) Context {
return c.withValue(key, value)
}
func (c Context) WithUint64(key interface{}, value uint64) Context {
return c.withValue(key, value)
}
func (c Context) withValue(key interface{}, value interface{}) Context {
return Context{context.WithValue(c.Context, key, value)}
}
@ -134,6 +139,10 @@ func (c Context) TxBytes() []byte {
return c.Value(contextKeyTxBytes).([]byte)
}
func (c Context) KVStore(key interface{}) KVStore {
return c.Value(key).(KVStore)
}
// Unexposed to prevent overriding.
func (c Context) setBlockHeader(header abci.Header) Context {
var _ proto.Message = &header // for cloning.

View File

@ -1,12 +1,12 @@
package types
// A Decorator executes before/during/after a handler to enhance functionality.
type Decorator func(ctx Context, ms MultiStore, tx Tx, next Handler) Result
type Decorator func(ctx Context, tx Tx, next Handler) Result
// Return a decorated handler
func Decorate(dec Decorator, next Handler) Handler {
return func(ctx Context, ms MultiStore, tx Tx) Result {
return dec(ctx, ms, tx, next)
return func(ctx Context, tx Tx) Result {
return dec(ctx, tx, next)
}
}

View File

@ -2,4 +2,4 @@ package types
// Handler handles both ABCI DeliverTx and CheckTx requests.
// Iff ABCI.CheckTx, ctx.IsCheckTx() returns true.
type Handler func(ctx Context, ms MultiStore, tx Tx) Result
type Handler func(ctx Context, tx Tx) Result

View File

@ -80,6 +80,12 @@ type CommitStoreLoader func(id CommitID) (CommitStore, error)
// KVStore is a simple interface to get/set data
type KVStore interface {
// TODO Not yet implemented.
// CreateSubKVStore(key *storeKey) (KVStore, error)
// TODO Not yet implemented.
// GetSubKVStore(key *storeKey) KVStore
// Get returns nil iff key doesn't exist. Panics on nil key.
Get(key []byte) []byte

View File

@ -8,7 +8,7 @@ type Msg interface {
Get(key interface{}) (value interface{})
// Get the canonical byte representation of the Msg.
SignBytes() []byte
GetSignBytes() []byte
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.

View File

@ -1,54 +0,0 @@
package account
import (
"encoding/json"
"path"
"github.com/cosmos/cosmos-sdk/types"
crypto "github.com/tendermint/go-crypto"
)
type AccountStore struct {
kvStore types.KVStore
}
func NewAccountStore(kvStore types.KVStore) types.AccountStore {
return AccountStore{kvStore}
}
func (accStore AccountStore) NewAccountWithAddress(addr crypto.Address) types.Account {
return NewBaseAccountWithAddress(addr)
}
func (accStore AccountStore) GetAccount(addr crypto.Address) types.Account {
v := accStore.kvStore.Get(keyAccount(addr))
if len(v) == 0 {
return nil
}
acc := new(BaseAccount)
if err := json.Unmarshal(v, acc); err != nil {
panic(err)
}
return acc
}
func (accStore AccountStore) SetAccount(acc types.Account) {
b, err := json.Marshal(acc)
if err != nil {
panic(err)
}
appAcc, ok := acc.(*BaseAccount)
if !ok {
panic("acc is not *BaseAccount") // XXX
}
accStore.kvStore.Set(keyAccount(appAcc.Address()), b)
}
func keyAccount(addr crypto.Address) []byte {
return []byte(path.Join("account", string(addr)))
}

View File

@ -1,4 +1,4 @@
package account
package auth
import (
"encoding/json"

View File

@ -1,4 +1,4 @@
package account
package auth
import (
"testing"

View File

@ -7,7 +7,6 @@ import (
crypto "github.com/tendermint/go-crypto"
"github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/coin"
)
//-----------------------------------------------------------------------------
@ -15,7 +14,7 @@ import (
// TxInput
type TxInput struct {
Address crypto.Address `json:"address"`
Coins Coins `json:"coins"`
Coins types.Coins `json:"coins"`
Sequence int64 `json:"sequence"`
signature crypto.Signature
@ -43,7 +42,7 @@ func (txIn TxInput) String() string {
}
// NewTxInput - create a transaction input, used with SendTx
func NewTxInput(addr crypto.Address, coins Coins) TxInput {
func NewTxInput(addr crypto.Address, coins types.Coins) TxInput {
input := TxInput{
Address: addr,
Coins: coins,
@ -52,7 +51,7 @@ func NewTxInput(addr crypto.Address, coins Coins) TxInput {
}
// NewTxInputWithSequence - create a transaction input, used with SendTx
func NewTxInputWithSequence(addr crypto.Address, coins Coins, seq int64) TxInput {
func NewTxInputWithSequence(addr crypto.Address, coins types.Coins, seq int64) TxInput {
input := NewTxInput(addr, coins)
input.Sequence = seq
return input
@ -63,7 +62,7 @@ func NewTxInputWithSequence(addr crypto.Address, coins Coins, seq int64) TxInput
// TxOutput - expected coin movement output, used with SendTx
type TxOutput struct {
Address crypto.Address `json:"address"`
Coins Coins `json:"coins"`
Coins types.Coins `json:"coins"`
}
// ValidateBasic - validate transaction output
@ -85,7 +84,7 @@ func (txOut TxOutput) String() string {
}
// NewTxOutput - create a transaction output, used with SendTx
func NewTxOutput(addr crypto.Address, coins Coins) TxOutput {
func NewTxOutput(addr crypto.Address, coins types.Coins) TxOutput {
output := TxOutput{
Address: addr,
Coins: coins,
@ -95,7 +94,12 @@ func NewTxOutput(addr crypto.Address, coins Coins) TxOutput {
//-----------------------------------------------------------------------------
var _ types.Tx = (*SendTx)(nil)
type CoinstoreTx interface {
Tx
AssertIsCoinstoreTx()
}
var _ CoinstoreTx = (*SendTx)(nil)
// SendTx - high level transaction of the coin module
type SendTx struct {
@ -103,6 +107,9 @@ type SendTx struct {
Outputs []TxOutput `json:"outputs"`
}
// Used to switch in the decorator to process all Coinstore txs.
func (tx SendTx) AssertIsCoinstoreTx() {}
// ValidateBasic - validate the send transaction
func (tx SendTx) ValidateBasic() error {
// this just makes sure all the inputs and outputs are properly formatted,
@ -114,7 +121,7 @@ func (tx SendTx) ValidateBasic() error {
return ErrNoOutputs()
}
// make sure all inputs and outputs are individually valid
var totalIn, totalOut Coins
var totalIn, totalOut types.Coins
for _, in := range tx.Inputs {
if err := in.ValidateBasic(); err != nil {
return err