Initial commit for permissioning...
This commit is contained in:
parent
d3de10e22b
commit
51e6144c0d
@ -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 {
|
||||
|
||||
@ -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}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -1,4 +1,4 @@
|
||||
package coin
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)))
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package account
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -1,4 +1,4 @@
|
||||
package account
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user