Abstracts away from pubkey addr -> app/chain-specific "actors"
This commit is contained in:
parent
1caeec218f
commit
4d0db39fb9
20
context.go
20
context.go
|
@ -2,21 +2,27 @@ package basecoin
|
|||
|
||||
import "github.com/tendermint/go-wire/data"
|
||||
|
||||
type Permission struct {
|
||||
App string // Which app authorized this?
|
||||
Address data.Bytes // App-specific identifier
|
||||
// Actor abstracts any address that can authorize actions, hold funds,
|
||||
// or initiate any sort of transaction.
|
||||
//
|
||||
// It doesn't just have to be a pubkey on this chain, it could stem from
|
||||
// another app (like multi-sig account), or even another chain (via IBC)
|
||||
type Actor struct {
|
||||
ChainID string // this is empty unless it comes from a different chain
|
||||
App string // the app that the actor belongs to
|
||||
Address data.Bytes // arbitrary app-specific unique id
|
||||
}
|
||||
|
||||
func NewPermission(app string, addr []byte) Permission {
|
||||
return Permission{App: app, Address: addr}
|
||||
func NewActor(app string, addr []byte) Actor {
|
||||
return Actor{App: app, Address: addr}
|
||||
}
|
||||
|
||||
// Context is an interface, so we can implement "secure" variants that
|
||||
// rely on private fields to control the actions
|
||||
type Context interface {
|
||||
// context.Context
|
||||
WithPermissions(perms ...Permission) Context
|
||||
HasPermission(perm Permission) bool
|
||||
WithPermissions(perms ...Actor) Context
|
||||
HasPermission(perm Actor) bool
|
||||
IsParent(ctx Context) bool
|
||||
Reset() Context
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ const (
|
|||
|
||||
type AccountChecker interface {
|
||||
// Get amount checks the current amount
|
||||
GetAmount(store types.KVStore, addr []byte) (types.Coins, error)
|
||||
GetAmount(store types.KVStore, addr basecoin.Actor) (types.Coins, error)
|
||||
|
||||
// ChangeAmount modifies the balance by the given amount and returns the new balance
|
||||
// always returns an error if leading to negative balance
|
||||
ChangeAmount(store types.KVStore, addr []byte, coins types.Coins) (types.Coins, error)
|
||||
ChangeAmount(store types.KVStore, addr basecoin.Actor, coins types.Coins) (types.Coins, error)
|
||||
}
|
||||
|
||||
type SimpleFeeHandler struct {
|
||||
|
@ -44,7 +44,7 @@ func (h SimpleFeeHandler) CheckTx(ctx basecoin.Context, store types.KVStore, tx
|
|||
return res, errors.InsufficientFees()
|
||||
}
|
||||
|
||||
if !ctx.HasPermission(SigPerm(feeTx.Payer)) {
|
||||
if !ctx.HasPermission(feeTx.Payer) {
|
||||
return res, errors.Unauthorized()
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ func (h SimpleFeeHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, t
|
|||
return res, errors.InsufficientFees()
|
||||
}
|
||||
|
||||
if !ctx.HasPermission(SigPerm(feeTx.Payer)) {
|
||||
if !ctx.HasPermission(feeTx.Payer) {
|
||||
return res, errors.Unauthorized()
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@ func (_ SignedHandler) Name() string {
|
|||
|
||||
var _ basecoin.Middleware = SignedHandler{}
|
||||
|
||||
func SigPerm(addr []byte) basecoin.Permission {
|
||||
return basecoin.Permission{App: NameSigs, Address: addr}
|
||||
func SigPerm(addr []byte) basecoin.Actor {
|
||||
return basecoin.NewActor(NameSigs, addr)
|
||||
}
|
||||
|
||||
// Signed allows us to use txs.OneSig and txs.MultiSig (and others??)
|
||||
|
@ -52,7 +52,7 @@ func (h SignedHandler) DeliverTx(ctx basecoin.Context, store types.KVStore, tx b
|
|||
}
|
||||
|
||||
func addSigners(ctx basecoin.Context, sigs []crypto.PubKey) basecoin.Context {
|
||||
perms := make([]basecoin.Permission, len(sigs))
|
||||
perms := make([]basecoin.Actor, len(sigs))
|
||||
for i, s := range sigs {
|
||||
perms[i] = SigPerm(s.Address())
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ type nonce int64
|
|||
type secureContext struct {
|
||||
id nonce
|
||||
app string
|
||||
perms []basecoin.Permission
|
||||
perms []basecoin.Actor
|
||||
}
|
||||
|
||||
func NewContext() basecoin.Context {
|
||||
|
@ -27,7 +27,7 @@ func NewContext() basecoin.Context {
|
|||
var _ basecoin.Context = secureContext{}
|
||||
|
||||
// WithPermissions will panic if they try to set permission without the proper app
|
||||
func (c secureContext) WithPermissions(perms ...basecoin.Permission) basecoin.Context {
|
||||
func (c secureContext) WithPermissions(perms ...basecoin.Actor) basecoin.Context {
|
||||
// the guard makes sure you only set permissions for the app you are inside
|
||||
for _, p := range perms {
|
||||
if p.App != c.app {
|
||||
|
@ -42,7 +42,7 @@ func (c secureContext) WithPermissions(perms ...basecoin.Permission) basecoin.Co
|
|||
}
|
||||
}
|
||||
|
||||
func (c secureContext) HasPermission(perm basecoin.Permission) bool {
|
||||
func (c secureContext) HasPermission(perm basecoin.Actor) bool {
|
||||
for _, p := range c.perms {
|
||||
if perm.App == p.App && bytes.Equal(perm.Address, p.Address) {
|
||||
return true
|
||||
|
|
10
txs/base.go
10
txs/base.go
|
@ -67,14 +67,14 @@ func NewRaw(d []byte) Raw {
|
|||
|
||||
// Fee attaches a fee payment to the embedded tx
|
||||
type Fee struct {
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
Fee types.Coin `json:"fee"`
|
||||
Payer data.Bytes `json:"payer"` // the address who pays the fee
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
Fee types.Coin `json:"fee"`
|
||||
Payer basecoin.Actor `json:"payer"` // the address who pays the fee
|
||||
// Gas types.Coin `json:"gas"` // ?????
|
||||
}
|
||||
|
||||
func NewFee(tx basecoin.Tx, fee types.Coin, addr []byte) *Fee {
|
||||
return &Fee{Tx: tx, Fee: fee, Payer: addr}
|
||||
func NewFee(tx basecoin.Tx, fee types.Coin, payer basecoin.Actor) *Fee {
|
||||
return &Fee{Tx: tx, Fee: fee, Payer: payer}
|
||||
}
|
||||
|
||||
func (f *Fee) ValidateBasic() error {
|
||||
|
|
21
txs/send.go
21
txs/send.go
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/tendermint/basecoin"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
|
||||
"github.com/tendermint/basecoin/errors"
|
||||
"github.com/tendermint/basecoin/types"
|
||||
|
@ -13,13 +12,14 @@ import (
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
type TxInput struct {
|
||||
Address data.Bytes `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
Sequence int `json:"sequence"` // Nonce: Must be 1 greater than the last committed TxInput
|
||||
Address basecoin.Actor `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
Sequence int `json:"sequence"` // Nonce: Must be 1 greater than the last committed TxInput
|
||||
}
|
||||
|
||||
func (txIn TxInput) ValidateBasic() error {
|
||||
if len(txIn.Address) != 20 {
|
||||
// TODO: knowledge of app-specific codings?
|
||||
if txIn.Address.App == "" {
|
||||
return errors.InvalidAddress()
|
||||
}
|
||||
if !txIn.Coins.IsValid() {
|
||||
|
@ -38,7 +38,7 @@ func (txIn TxInput) String() string {
|
|||
return fmt.Sprintf("TxInput{%v,%v,%v}", txIn.Address, txIn.Coins, txIn.Sequence)
|
||||
}
|
||||
|
||||
func NewTxInput(addr []byte, coins types.Coins, sequence int) TxInput {
|
||||
func NewTxInput(addr basecoin.Actor, coins types.Coins, sequence int) TxInput {
|
||||
input := TxInput{
|
||||
Address: addr,
|
||||
Coins: coins,
|
||||
|
@ -50,12 +50,13 @@ func NewTxInput(addr []byte, coins types.Coins, sequence int) TxInput {
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
type TxOutput struct {
|
||||
Address data.Bytes `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
Address basecoin.Actor `json:"address"`
|
||||
Coins types.Coins `json:"coins"`
|
||||
}
|
||||
|
||||
func (txOut TxOutput) ValidateBasic() error {
|
||||
if len(txOut.Address) != 20 {
|
||||
// TODO: knowledge of app-specific codings?
|
||||
if txOut.Address.App == "" {
|
||||
return errors.InvalidAddress()
|
||||
}
|
||||
if !txOut.Coins.IsValid() {
|
||||
|
@ -71,7 +72,7 @@ func (txOut TxOutput) String() string {
|
|||
return fmt.Sprintf("TxOutput{%X,%v}", txOut.Address, txOut.Coins)
|
||||
}
|
||||
|
||||
func NewTxOutput(addr []byte, coins types.Coins) TxOutput {
|
||||
func NewTxOutput(addr basecoin.Actor, coins types.Coins) TxOutput {
|
||||
output := TxOutput{
|
||||
Address: addr,
|
||||
Coins: coins,
|
||||
|
|
Loading…
Reference in New Issue