mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-25 02:31:46 +00:00
PermFlag rename; Make Permission fields value (nonpointer) fields; Permissions & Snatives on by default; Remove dead code
This commit is contained in:
2
Makefile
2
Makefile
@ -28,7 +28,7 @@ test: build
|
|||||||
draw_deps:
|
draw_deps:
|
||||||
# requires brew install graphviz
|
# requires brew install graphviz
|
||||||
go get github.com/hirokidaichi/goviz
|
go get github.com/hirokidaichi/goviz
|
||||||
goviz -i github.com/tendermint/tendermint/cmd/tendermint | dot -Tpng -o hoge.png
|
goviz -i github.com/tendermint/tendermint/cmd/tendermint | dot -Tpng -o huge.png
|
||||||
|
|
||||||
list_deps:
|
list_deps:
|
||||||
go list -f '{{join .Deps "\n"}}' github.com/tendermint/tendermint/... | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}'
|
go list -f '{{join .Deps "\n"}}' github.com/tendermint/tendermint/... | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}'
|
||||||
|
@ -45,7 +45,7 @@ type Account struct {
|
|||||||
Code []byte `json:"code"` // VM code
|
Code []byte `json:"code"` // VM code
|
||||||
StorageRoot []byte `json:"storage_root"` // VM storage merkle root.
|
StorageRoot []byte `json:"storage_root"` // VM storage merkle root.
|
||||||
|
|
||||||
Permissions *ptypes.AccountPermissions `json:"permissions"`
|
Permissions ptypes.AccountPermissions `json:"permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (acc *Account) Copy() *Account {
|
func (acc *Account) Copy() *Account {
|
||||||
@ -55,7 +55,7 @@ func (acc *Account) Copy() *Account {
|
|||||||
|
|
||||||
func (acc *Account) String() string {
|
func (acc *Account) String() string {
|
||||||
// return fmt.Sprintf("Account{%X:%v C:%v S:%X}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot)
|
// return fmt.Sprintf("Account{%X:%v C:%v S:%X}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot)
|
||||||
return fmt.Sprintf("Account{%X:%v C:%v S:%X P:(%s)}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot, acc.Permissions)
|
return fmt.Sprintf("Account{%X:%v C:%v S:%X P:%s}", acc.Address, acc.PubKey, len(acc.Code), acc.StorageRoot, acc.Permissions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AccountEncoder(o interface{}, w io.Writer, n *int64, err *error) {
|
func AccountEncoder(o interface{}, w io.Writer, n *int64, err *error) {
|
||||||
|
@ -14,27 +14,6 @@ func (e ErrInvalidPermission) Error() string {
|
|||||||
return fmt.Sprintf("invalid permission %d", e)
|
return fmt.Sprintf("invalid permission %d", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unknown string for permission
|
|
||||||
type ErrInvalidPermissionString string
|
|
||||||
|
|
||||||
func (e ErrInvalidPermissionString) Error() string {
|
|
||||||
return fmt.Sprintf("invalid permission '%s'", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// already exists (err on add)
|
|
||||||
type ErrPermissionExists string
|
|
||||||
|
|
||||||
func (e ErrPermissionExists) Error() string {
|
|
||||||
return fmt.Sprintf("permission '%s' already exists", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown string for snative contract
|
|
||||||
type ErrInvalidSNativeString string
|
|
||||||
|
|
||||||
func (e ErrInvalidSNativeString) Error() string {
|
|
||||||
return fmt.Sprintf("invalid snative contract '%s'", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set=false. This error should be caught and the global
|
// set=false. This error should be caught and the global
|
||||||
// value fetched for the permission by the caller
|
// value fetched for the permission by the caller
|
||||||
type ErrValueNotSet PermFlag
|
type ErrValueNotSet PermFlag
|
||||||
|
@ -3,7 +3,6 @@ package types
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------
|
||||||
@ -20,34 +19,34 @@ type PermFlag uint64
|
|||||||
|
|
||||||
// Base permission references are like unix (the index is already bit shifted)
|
// Base permission references are like unix (the index is already bit shifted)
|
||||||
const (
|
const (
|
||||||
Root PermFlag = 1 << iota // 1
|
Root PermFlag = 1 << iota // 1
|
||||||
Send // 2
|
Send // 2
|
||||||
Call // 4
|
Call // 4
|
||||||
CreateContract // 8
|
CreateContract // 8
|
||||||
CreateAccount // 16
|
CreateAccount // 16
|
||||||
Bond // 32
|
Bond // 32
|
||||||
Name // 64
|
Name // 64
|
||||||
|
NumBasePermissions uint = 7 // NOTE Adjust this too.
|
||||||
|
|
||||||
DefaultBBPB = Send | Call | CreateContract | CreateAccount | Bond | Name
|
TopBasePermFlag PermFlag = 1 << (NumBasePermissions - 1)
|
||||||
|
AllBasePermFlags PermFlag = TopBasePermFlag | (TopBasePermFlag - 1)
|
||||||
// XXX: must be adjusted if base perms added/removed
|
AllPermFlags PermFlag = AllBasePermFlags | AllSNativePermFlags
|
||||||
NumBasePermissions uint = 7
|
DefaultBasePermFlags PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name
|
||||||
TopBasePermission PermFlag = 1 << (NumBasePermissions - 1)
|
|
||||||
AllBasePermissions PermFlag = TopBasePermission | (TopBasePermission - 1)
|
|
||||||
|
|
||||||
AllSet PermFlag = AllBasePermissions | AllSNativePermissions
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// should have same ordering as above
|
var (
|
||||||
type BasePermissionsString struct {
|
ZeroBasePermissions = BasePermissions{0, 0}
|
||||||
Root bool `json:"root,omitempty"`
|
ZeroAccountPermissions = AccountPermissions{
|
||||||
Send bool `json:"send,omitempty"`
|
Base: ZeroBasePermissions,
|
||||||
Call bool `json:"call,omitempty"`
|
}
|
||||||
CreateContract bool `json:"create_contract,omitempty"`
|
DefaultAccountPermissions = AccountPermissions{
|
||||||
CreateAccount bool `json:"create_account,omitempty"`
|
Base: BasePermissions{
|
||||||
Bond bool `json:"bond,omitempty"`
|
Perms: DefaultBasePermFlags,
|
||||||
Name bool `json:"name,omitempty"`
|
SetBit: AllPermFlags,
|
||||||
}
|
},
|
||||||
|
Roles: []string{},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -60,10 +59,6 @@ type BasePermissions struct {
|
|||||||
SetBit PermFlag `json:"set"`
|
SetBit PermFlag `json:"set"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasePermissions() *BasePermissions {
|
|
||||||
return &BasePermissions{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a permission value. ty should be a power of 2.
|
// Get a permission value. ty should be a power of 2.
|
||||||
// ErrValueNotSet is returned if the permission's set bit is off,
|
// ErrValueNotSet is returned if the permission's set bit is off,
|
||||||
// and should be caught by caller so the global permission can be fetched
|
// and should be caught by caller so the global permission can be fetched
|
||||||
@ -108,32 +103,15 @@ func (p *BasePermissions) IsSet(ty PermFlag) bool {
|
|||||||
return p.SetBit&ty > 0
|
return p.SetBit&ty > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePermissions) Copy() *BasePermissions {
|
func (p BasePermissions) String() string {
|
||||||
if p == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &BasePermissions{
|
|
||||||
Perms: p.Perms,
|
|
||||||
SetBit: p.SetBit,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *BasePermissions) String() string {
|
|
||||||
return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
|
return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
type AccountPermissions struct {
|
type AccountPermissions struct {
|
||||||
Base *BasePermissions `json:"base"`
|
Base BasePermissions `json:"base"`
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
}
|
|
||||||
|
|
||||||
func NewAccountPermissions() *AccountPermissions {
|
|
||||||
return &AccountPermissions{
|
|
||||||
Base: NewBasePermissions(),
|
|
||||||
Roles: []string{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the role is found
|
// Returns true if the role is found
|
||||||
@ -175,75 +153,7 @@ func (aP *AccountPermissions) RmRole(role string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aP *AccountPermissions) Copy() *AccountPermissions {
|
//--------------------------------------------------------------------------------
|
||||||
if aP == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
r := make([]string, len(aP.Roles))
|
|
||||||
copy(r, aP.Roles)
|
|
||||||
return &AccountPermissions{
|
|
||||||
Base: aP.Base.Copy(),
|
|
||||||
Roles: r,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultAccountPermissions() *AccountPermissions {
|
|
||||||
return &AccountPermissions{
|
|
||||||
Base: &BasePermissions{
|
|
||||||
Perms: DefaultBBPB,
|
|
||||||
SetBit: AllSet,
|
|
||||||
},
|
|
||||||
Roles: []string{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------
|
|
||||||
// Utilities to make bitmasks human readable
|
|
||||||
|
|
||||||
func NewDefaultAccountPermissionsString() BasePermissionsString {
|
|
||||||
return BasePermissionsString{
|
|
||||||
Root: false,
|
|
||||||
Bond: true,
|
|
||||||
Send: true,
|
|
||||||
Call: true,
|
|
||||||
Name: true,
|
|
||||||
CreateAccount: true,
|
|
||||||
CreateContract: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AccountPermissionsFromStrings(perms *BasePermissionsString, roles []string) (*AccountPermissions, error) {
|
|
||||||
base := NewBasePermissions()
|
|
||||||
permRv := reflect.ValueOf(perms)
|
|
||||||
for i := uint(0); i < uint(permRv.NumField()); i++ {
|
|
||||||
v := permRv.Field(int(i)).Bool()
|
|
||||||
base.Set(1<<i, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
aP := &AccountPermissions{
|
|
||||||
Base: base,
|
|
||||||
Roles: make([]string, len(roles)),
|
|
||||||
}
|
|
||||||
copy(aP.Roles, roles)
|
|
||||||
return aP, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func AccountPermissionsToStrings(aP *AccountPermissions) (*BasePermissionsString, []string, error) {
|
|
||||||
perms := new(BasePermissionsString)
|
|
||||||
permsRv := reflect.ValueOf(perms).Elem()
|
|
||||||
for i := uint(0); i < NumBasePermissions; i++ {
|
|
||||||
pf := PermFlag(1 << i)
|
|
||||||
if aP.Base.IsSet(pf) {
|
|
||||||
// won't err if the bit is set
|
|
||||||
v, _ := aP.Base.Get(pf)
|
|
||||||
f := permsRv.Field(int(i))
|
|
||||||
f.SetBool(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roles := make([]string, len(aP.Roles))
|
|
||||||
copy(roles, aP.Roles)
|
|
||||||
return perms, roles, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PermFlagToString(pf PermFlag) (perm string, err error) {
|
func PermFlagToString(pf PermFlag) (perm string, err error) {
|
||||||
switch pf {
|
switch pf {
|
||||||
|
@ -2,13 +2,13 @@ package types
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// first 32 bits of BasePermission are for chain, second 32 are for snative
|
// first 32 bits of BasePermission are for chain, second 32 are for snative
|
||||||
FirstSNativePerm PermFlag = 1 << 32
|
FirstSNativePermFlag PermFlag = 1 << 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// we need to reset iota with no const block
|
// we need to reset iota with no const block
|
||||||
const (
|
const (
|
||||||
// each snative has an associated permission flag
|
// each snative has an associated permission flag
|
||||||
HasBasePerm PermFlag = FirstSNativePerm << iota
|
HasBasePerm PermFlag = FirstSNativePermFlag << iota
|
||||||
SetBasePerm
|
SetBasePerm
|
||||||
UnsetBasePerm
|
UnsetBasePerm
|
||||||
SetGlobalPerm
|
SetGlobalPerm
|
||||||
@ -16,9 +16,8 @@ const (
|
|||||||
HasRole
|
HasRole
|
||||||
AddRole
|
AddRole
|
||||||
RmRole
|
RmRole
|
||||||
|
NumSNativePermissions uint = 8 // NOTE adjust this too
|
||||||
|
|
||||||
// XXX: must be adjusted if snative's added/removed
|
TopSNativePermFlag PermFlag = FirstSNativePermFlag << (NumSNativePermissions - 1)
|
||||||
NumSNativePermissions uint = 8
|
AllSNativePermFlags PermFlag = (TopSNativePermFlag | (TopSNativePermFlag - 1)) &^ (FirstSNativePermFlag - 1)
|
||||||
TopSNativePermission PermFlag = FirstSNativePerm << (NumSNativePermissions - 1)
|
|
||||||
AllSNativePermissions PermFlag = (TopSNativePermission | (TopSNativePermission - 1)) &^ (FirstSNativePerm - 1)
|
|
||||||
)
|
)
|
||||||
|
@ -187,7 +187,7 @@ func getOrMakeOutputs(state AccountGetter, accounts map[string]*account.Account,
|
|||||||
PubKey: nil,
|
PubKey: nil,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
Balance: 0,
|
Balance: 0,
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accounts[string(out.Address)] = acc
|
accounts[string(out.Address)] = acc
|
||||||
@ -293,7 +293,8 @@ func adjustByOutputs(accounts map[string]*account.Account, outs []*types.TxOutpu
|
|||||||
|
|
||||||
// If the tx is invalid, an error will be returned.
|
// If the tx is invalid, an error will be returned.
|
||||||
// Unlike ExecBlock(), state will not be altered.
|
// Unlike ExecBlock(), state will not be altered.
|
||||||
func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Fireable) error {
|
func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Fireable) (err error) {
|
||||||
|
|
||||||
// TODO: do something with fees
|
// TODO: do something with fees
|
||||||
fees := int64(0)
|
fees := int64(0)
|
||||||
_s := blockCache.State() // hack to access validators and block height
|
_s := blockCache.State() // hack to access validators and block height
|
||||||
@ -467,9 +468,6 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
|
|||||||
vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx))
|
vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx))
|
||||||
vmach.SetFireable(evc)
|
vmach.SetFireable(evc)
|
||||||
|
|
||||||
vmach.EnablePermissions() // permission checks on CALL/CREATE
|
|
||||||
vmach.EnableSNatives() // allows calls to snatives (with permission checks)
|
|
||||||
|
|
||||||
// NOTE: Call() transfers the value from caller to callee iff call succeeds.
|
// NOTE: Call() transfers the value from caller to callee iff call succeeds.
|
||||||
ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
|
ret, err := vmach.Call(caller, callee, code, tx.Data, value, &gas)
|
||||||
exception := ""
|
exception := ""
|
||||||
@ -814,7 +812,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
|
|||||||
|
|
||||||
// Get permission on an account or fall back to global value
|
// Get permission on an account or fall back to global value
|
||||||
func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFlag) bool {
|
func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFlag) bool {
|
||||||
if perm > ptypes.AllBasePermissions {
|
if perm > ptypes.AllBasePermFlags {
|
||||||
panic("Checking an unknown permission in state should never happen")
|
panic("Checking an unknown permission in state should never happen")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,10 +824,14 @@ func HasPermission(state AccountGetter, acc *account.Account, perm ptypes.PermFl
|
|||||||
|
|
||||||
v, err := acc.Permissions.Base.Get(perm)
|
v, err := acc.Permissions.Base.Get(perm)
|
||||||
if _, ok := err.(ptypes.ErrValueNotSet); ok {
|
if _, ok := err.(ptypes.ErrValueNotSet); ok {
|
||||||
|
log.Debug("Account does not have permission", "account", acc, "accPermissions", acc.Permissions, "perm", perm)
|
||||||
if state == nil {
|
if state == nil {
|
||||||
panic("All known global permissions should be set!")
|
panic("All known global permissions should be set!")
|
||||||
}
|
}
|
||||||
|
log.Debug("Querying GlobalPermissionsAddress")
|
||||||
return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
|
return HasPermission(nil, state.GetAccount(ptypes.GlobalPermissionsAddress), perm)
|
||||||
|
} else {
|
||||||
|
log.Debug("Account has permission", "account", acc, "accPermissions", acc.Permissions, "perm", perm)
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
|
|||||||
// Make accounts state tree
|
// Make accounts state tree
|
||||||
accounts := merkle.NewIAVLTree(binary.BasicCodec, account.AccountCodec, defaultAccountsCacheCapacity, db)
|
accounts := merkle.NewIAVLTree(binary.BasicCodec, account.AccountCodec, defaultAccountsCacheCapacity, db)
|
||||||
for _, genAcc := range genDoc.Accounts {
|
for _, genAcc := range genDoc.Accounts {
|
||||||
perm := ptypes.NewDefaultAccountPermissions()
|
perm := ptypes.ZeroAccountPermissions
|
||||||
if genAcc.Permissions != nil {
|
if genAcc.Permissions != nil {
|
||||||
perm = genAcc.Permissions
|
perm = *genAcc.Permissions
|
||||||
}
|
}
|
||||||
acc := &account.Account{
|
acc := &account.Account{
|
||||||
Address: genAcc.Address,
|
Address: genAcc.Address,
|
||||||
@ -104,12 +104,12 @@ func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
|
|||||||
|
|
||||||
// global permissions are saved as the 0 address
|
// global permissions are saved as the 0 address
|
||||||
// so they are included in the accounts tree
|
// so they are included in the accounts tree
|
||||||
globalPerms := ptypes.NewDefaultAccountPermissions()
|
globalPerms := ptypes.DefaultAccountPermissions
|
||||||
if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
|
if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
|
||||||
globalPerms = genDoc.Params.GlobalPermissions
|
globalPerms = *genDoc.Params.GlobalPermissions
|
||||||
// XXX: make sure the set bits are all true
|
// XXX: make sure the set bits are all true
|
||||||
// Without it the HasPermission() functions will fail
|
// Without it the HasPermission() functions will fail
|
||||||
globalPerms.Base.SetBit = ptypes.AllSet
|
globalPerms.Base.SetBit = ptypes.AllPermFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
permsAcc := &account.Account{
|
permsAcc := &account.Account{
|
||||||
|
@ -92,16 +92,17 @@ func makeUsers(n int) []*account.PrivAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
PermsAllFalse = ptypes.NewAccountPermissions()
|
PermsAllFalse = ptypes.ZeroAccountPermissions
|
||||||
)
|
)
|
||||||
|
|
||||||
func newBaseGenDoc(globalPerm, accountPerm *ptypes.AccountPermissions) GenesisDoc {
|
func newBaseGenDoc(globalPerm, accountPerm ptypes.AccountPermissions) GenesisDoc {
|
||||||
genAccounts := []GenesisAccount{}
|
genAccounts := []GenesisAccount{}
|
||||||
for _, u := range user[:5] {
|
for _, u := range user[:5] {
|
||||||
|
accountPermCopy := accountPerm // Create new instance for custom overridability.
|
||||||
genAccounts = append(genAccounts, GenesisAccount{
|
genAccounts = append(genAccounts, GenesisAccount{
|
||||||
Address: u.Address,
|
Address: u.Address,
|
||||||
Amount: 1000000,
|
Amount: 1000000,
|
||||||
Permissions: accountPerm.Copy(),
|
Permissions: &accountPermCopy,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ func newBaseGenDoc(globalPerm, accountPerm *ptypes.AccountPermissions) GenesisDo
|
|||||||
GenesisTime: time.Now(),
|
GenesisTime: time.Now(),
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
Params: &GenesisParams{
|
Params: &GenesisParams{
|
||||||
GlobalPermissions: globalPerm,
|
GlobalPermissions: &globalPerm,
|
||||||
},
|
},
|
||||||
Accounts: genAccounts,
|
Accounts: genAccounts,
|
||||||
Validators: []GenesisValidator{
|
Validators: []GenesisValidator{
|
||||||
@ -353,7 +354,7 @@ func TestCallPermission(t *testing.T) {
|
|||||||
Code: []byte{0x60},
|
Code: []byte{0x60},
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
st.UpdateAccount(simpleAcc)
|
st.UpdateAccount(simpleAcc)
|
||||||
|
|
||||||
@ -377,7 +378,7 @@ func TestCallPermission(t *testing.T) {
|
|||||||
Code: contractCode,
|
Code: contractCode,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
blockCache.UpdateAccount(caller1Acc)
|
blockCache.UpdateAccount(caller1Acc)
|
||||||
|
|
||||||
@ -421,7 +422,7 @@ func TestCallPermission(t *testing.T) {
|
|||||||
Code: contractCode2,
|
Code: contractCode2,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
caller1Acc.Permissions.Base.Set(ptypes.Call, false)
|
caller1Acc.Permissions.Base.Set(ptypes.Call, false)
|
||||||
caller2Acc.Permissions.Base.Set(ptypes.Call, true)
|
caller2Acc.Permissions.Base.Set(ptypes.Call, true)
|
||||||
@ -553,7 +554,7 @@ func TestCreatePermission(t *testing.T) {
|
|||||||
Code: code,
|
Code: code,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
contractAcc.Permissions.Base.Set(ptypes.Call, true)
|
contractAcc.Permissions.Base.Set(ptypes.Call, true)
|
||||||
contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
|
contractAcc.Permissions.Base.Set(ptypes.CreateContract, true)
|
||||||
@ -805,7 +806,7 @@ func TestCreateAccountPermission(t *testing.T) {
|
|||||||
Code: contractCode,
|
Code: contractCode,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
blockCache.UpdateAccount(caller1Acc)
|
blockCache.UpdateAccount(caller1Acc)
|
||||||
|
|
||||||
@ -856,7 +857,7 @@ func TestSNativeCALL(t *testing.T) {
|
|||||||
Code: nil,
|
Code: nil,
|
||||||
Sequence: 0,
|
Sequence: 0,
|
||||||
StorageRoot: Zero256.Bytes(),
|
StorageRoot: Zero256.Bytes(),
|
||||||
Permissions: ptypes.NewAccountPermissions(),
|
Permissions: ptypes.ZeroAccountPermissions,
|
||||||
}
|
}
|
||||||
doug.Permissions.Base.Set(ptypes.Call, true)
|
doug.Permissions.Base.Set(ptypes.Call, true)
|
||||||
blockCache.UpdateAccount(doug)
|
blockCache.UpdateAccount(doug)
|
||||||
|
@ -25,7 +25,7 @@ func Tempfile(prefix string) (*os.File, string) {
|
|||||||
|
|
||||||
func RandAccount(randBalance bool, minBalance int64) (*account.Account, *account.PrivAccount) {
|
func RandAccount(randBalance bool, minBalance int64) (*account.Account, *account.PrivAccount) {
|
||||||
privAccount := account.GenPrivAccount()
|
privAccount := account.GenPrivAccount()
|
||||||
perms := ptypes.NewDefaultAccountPermissions()
|
perms := ptypes.DefaultAccountPermissions
|
||||||
acc := &account.Account{
|
acc := &account.Account{
|
||||||
Address: privAccount.PubKey.Address(),
|
Address: privAccount.PubKey.Address(),
|
||||||
PubKey: privAccount.PubKey,
|
PubKey: privAccount.PubKey,
|
||||||
@ -73,12 +73,13 @@ func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numVa
|
|||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
accounts := make([]GenesisAccount, numAccounts)
|
accounts := make([]GenesisAccount, numAccounts)
|
||||||
privAccounts := make([]*account.PrivAccount, numAccounts)
|
privAccounts := make([]*account.PrivAccount, numAccounts)
|
||||||
|
defaultPerms := ptypes.DefaultAccountPermissions
|
||||||
for i := 0; i < numAccounts; i++ {
|
for i := 0; i < numAccounts; i++ {
|
||||||
account, privAccount := RandAccount(randBalance, minBalance)
|
account, privAccount := RandAccount(randBalance, minBalance)
|
||||||
accounts[i] = GenesisAccount{
|
accounts[i] = GenesisAccount{
|
||||||
Address: account.Address,
|
Address: account.Address,
|
||||||
Amount: account.Balance,
|
Amount: account.Balance,
|
||||||
Permissions: ptypes.NewDefaultAccountPermissions(),
|
Permissions: &defaultPerms, // This will get copied into each state.Account.
|
||||||
}
|
}
|
||||||
privAccounts[i] = privAccount
|
privAccounts[i] = privAccount
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numVa
|
|||||||
Accounts: accounts,
|
Accounts: accounts,
|
||||||
Validators: validators,
|
Validators: validators,
|
||||||
Params: &GenesisParams{
|
Params: &GenesisParams{
|
||||||
GlobalPermissions: ptypes.NewDefaultAccountPermissions(),
|
GlobalPermissions: &defaultPerms,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
s0.Save()
|
s0.Save()
|
||||||
|
@ -165,7 +165,7 @@ func toVMAccount(acc *ac.Account) *vm.Account {
|
|||||||
Code: acc.Code, // This is crazy.
|
Code: acc.Code, // This is crazy.
|
||||||
Nonce: int64(acc.Sequence),
|
Nonce: int64(acc.Sequence),
|
||||||
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
||||||
Permissions: acc.Permissions.Copy(),
|
Permissions: acc.Permissions, // Copy
|
||||||
Other: acc.PubKey,
|
Other: acc.PubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ func toStateAccount(acc *vm.Account) *ac.Account {
|
|||||||
Code: acc.Code,
|
Code: acc.Code,
|
||||||
Sequence: int(acc.Nonce),
|
Sequence: int(acc.Nonce),
|
||||||
StorageRoot: storageRoot,
|
StorageRoot: storageRoot,
|
||||||
Permissions: acc.Permissions,
|
Permissions: acc.Permissions, // Copy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,9 +224,9 @@ func (e ErrInvalidPermission) Error() string {
|
|||||||
|
|
||||||
// Checks if a permission flag is valid (a known base chain or snative permission)
|
// Checks if a permission flag is valid (a known base chain or snative permission)
|
||||||
func ValidPermN(n ptypes.PermFlag) bool {
|
func ValidPermN(n ptypes.PermFlag) bool {
|
||||||
if n > ptypes.TopBasePermission && n < ptypes.FirstSNativePerm {
|
if n > ptypes.TopBasePermFlag && n < ptypes.FirstSNativePermFlag {
|
||||||
return false
|
return false
|
||||||
} else if n > ptypes.TopSNativePermission {
|
} else if n > ptypes.TopSNativePermFlag {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -10,16 +10,22 @@ import (
|
|||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
. "github.com/tendermint/tendermint/vm"
|
. "github.com/tendermint/tendermint/vm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newAppState() *FakeAppState {
|
func newAppState() *FakeAppState {
|
||||||
return &FakeAppState{
|
fas := &FakeAppState{
|
||||||
accounts: make(map[string]*Account),
|
accounts: make(map[string]*Account),
|
||||||
storage: make(map[string]Word256),
|
storage: make(map[string]Word256),
|
||||||
logs: nil,
|
logs: nil,
|
||||||
}
|
}
|
||||||
|
// For default permissions
|
||||||
|
fas.accounts[ptypes.GlobalPermissionsAddress256.String()] = &Account{
|
||||||
|
Permissions: ptypes.DefaultAccountPermissions,
|
||||||
|
}
|
||||||
|
return fas
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParams() Params {
|
func newParams() Params {
|
||||||
|
@ -17,7 +17,7 @@ type Account struct {
|
|||||||
StorageRoot Word256
|
StorageRoot Word256
|
||||||
Other interface{} // For holding all other data.
|
Other interface{} // For holding all other data.
|
||||||
|
|
||||||
Permissions *ptypes.AccountPermissions
|
Permissions ptypes.AccountPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (acc *Account) String() string {
|
func (acc *Account) String() string {
|
||||||
|
31
vm/vm.go
31
vm/vm.go
@ -60,9 +60,6 @@ type VM struct {
|
|||||||
callDepth int
|
callDepth int
|
||||||
|
|
||||||
evc events.Fireable
|
evc events.Fireable
|
||||||
|
|
||||||
perms bool // permission checking can be turned off
|
|
||||||
snative bool // access to snatives
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM {
|
func NewVM(appState AppState, params Params, origin Word256, txid []byte) *VM {
|
||||||
@ -80,25 +77,17 @@ func (vm *VM) SetFireable(evc events.Fireable) {
|
|||||||
vm.evc = evc
|
vm.evc = evc
|
||||||
}
|
}
|
||||||
|
|
||||||
// to allow calls to native DougContracts (off by default)
|
// CONTRACT: it is the duty of the contract writer to call known permissions
|
||||||
func (vm *VM) EnableSNatives() {
|
|
||||||
vm.snative = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// run permission checks before call and create
|
|
||||||
func (vm *VM) EnablePermissions() {
|
|
||||||
vm.perms = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: it is the duty of the contract writer to call known permissions
|
|
||||||
// we do not convey if a permission is not set
|
// we do not convey if a permission is not set
|
||||||
// (unlike in state/execution, where we guarantee HasPermission is called
|
// (unlike in state/execution, where we guarantee HasPermission is called
|
||||||
// on known permissions and panics else)
|
// on known permissions and panics else)
|
||||||
|
// If the perm is not defined in the acc nor set by default in GlobalPermissions,
|
||||||
|
// prints a log warning and returns false.
|
||||||
func HasPermission(appState AppState, acc *Account, perm ptypes.PermFlag) bool {
|
func HasPermission(appState AppState, acc *Account, perm ptypes.PermFlag) bool {
|
||||||
v, err := acc.Permissions.Base.Get(perm)
|
v, err := acc.Permissions.Base.Get(perm)
|
||||||
if _, ok := err.(ptypes.ErrValueNotSet); ok {
|
if _, ok := err.(ptypes.ErrValueNotSet); ok {
|
||||||
if appState == nil {
|
if appState == nil {
|
||||||
fmt.Printf("\n\n***** Unknown permission %b! ********\n\n", perm)
|
log.Warn(Fmt("\n\n***** Unknown permission %b! ********\n\n", perm))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return HasPermission(nil, appState.GetAccount(ptypes.GlobalPermissionsAddress256), perm)
|
return HasPermission(nil, appState.GetAccount(ptypes.GlobalPermissionsAddress256), perm)
|
||||||
@ -125,8 +114,9 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// SNATIVE ACCESS
|
||||||
// if code is empty, callee may be snative contract
|
// if code is empty, callee may be snative contract
|
||||||
if vm.snative && len(code) == 0 {
|
if len(code) == 0 {
|
||||||
if snativeContract, ok := RegisteredSNativeContracts[callee.Address]; ok {
|
if snativeContract, ok := RegisteredSNativeContracts[callee.Address]; ok {
|
||||||
output, err = snativeContract(vm.appState, caller, input)
|
output, err = snativeContract(vm.appState, caller, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -135,6 +125,7 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// SNATIVE ACCESS END
|
||||||
|
|
||||||
if err = transfer(caller, callee, value); err != nil {
|
if err = transfer(caller, callee, value); err != nil {
|
||||||
*exception = err.Error()
|
*exception = err.Error()
|
||||||
@ -708,7 +699,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
dbg.Printf(" => %v\n", log)
|
dbg.Printf(" => %v\n", log)
|
||||||
|
|
||||||
case CREATE: // 0xF0
|
case CREATE: // 0xF0
|
||||||
if vm.perms && !HasPermission(vm.appState, callee, ptypes.CreateContract) {
|
if !HasPermission(vm.appState, callee, ptypes.CreateContract) {
|
||||||
return nil, ErrPermission{"create_contract"}
|
return nil, ErrPermission{"create_contract"}
|
||||||
}
|
}
|
||||||
contractValue := stack.Pop64()
|
contractValue := stack.Pop64()
|
||||||
@ -736,7 +727,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
}
|
}
|
||||||
|
|
||||||
case CALL, CALLCODE: // 0xF1, 0xF2
|
case CALL, CALLCODE: // 0xF1, 0xF2
|
||||||
if vm.perms && !HasPermission(vm.appState, callee, ptypes.Call) {
|
if !HasPermission(vm.appState, callee, ptypes.Call) {
|
||||||
return nil, ErrPermission{"call"}
|
return nil, ErrPermission{"call"}
|
||||||
}
|
}
|
||||||
gasLimit := stack.Pop64()
|
gasLimit := stack.Pop64()
|
||||||
@ -782,12 +773,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
||||||
} else {
|
} else {
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
if _, ok := RegisteredSNativeContracts[addr]; vm.snative && ok {
|
if _, ok := RegisteredSNativeContracts[addr]; ok {
|
||||||
acc = &Account{Address: addr}
|
acc = &Account{Address: addr}
|
||||||
} else {
|
} else {
|
||||||
// if we have not seen the account before, create it
|
// if we have not seen the account before, create it
|
||||||
// so we can send funds
|
// so we can send funds
|
||||||
if vm.perms && !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
|
if !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
|
||||||
return nil, ErrPermission{"create_account"}
|
return nil, ErrPermission{"create_account"}
|
||||||
}
|
}
|
||||||
acc = &Account{Address: addr}
|
acc = &Account{Address: addr}
|
||||||
|
Reference in New Issue
Block a user