|
package vm
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
. "github.com/tendermint/tendermint/common"
|
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
|
)
|
|
|
|
type SNativeContract func(input []byte) (output []byte, err error)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// snative are native contracts that can access and manipulate the chain state
|
|
// (in particular the permissions values)
|
|
|
|
// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
|
|
|
|
func (vm *VM) hasBasePerm(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permission number)")
|
|
}
|
|
var addr, permNum Word256
|
|
copy(addr[:], args[:32])
|
|
copy(permNum[:], args[32:64])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
permN := ptypes.PermFlag(Uint64FromWord256(permNum))
|
|
var permInt byte
|
|
if vm.HasPermission(vmAcc, permN) {
|
|
permInt = 0x1
|
|
} else {
|
|
permInt = 0x0
|
|
}
|
|
return LeftPadWord256([]byte{permInt}).Bytes(), nil
|
|
}
|
|
|
|
func (vm *VM) setBasePerm(args []byte) (output []byte, err error) {
|
|
if len(args) != 3*32 {
|
|
return nil, fmt.Errorf("setBasePerm() takes three arguments (address, permission number, permission value)")
|
|
}
|
|
var addr, permNum, perm Word256
|
|
copy(addr[:], args[:32])
|
|
copy(permNum[:], args[32:64])
|
|
copy(perm[:], args[64:96])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
permN := ptypes.PermFlag(Uint64FromWord256(permNum))
|
|
permV := !perm.IsZero()
|
|
if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
|
|
return nil, err
|
|
}
|
|
vm.appState.UpdateAccount(vmAcc)
|
|
return perm.Bytes(), nil
|
|
}
|
|
|
|
func (vm *VM) unsetBasePerm(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("unsetBasePerm() takes two arguments (address, permission number)")
|
|
}
|
|
var addr, permNum Word256
|
|
copy(addr[:], args[:32])
|
|
copy(permNum[:], args[32:64])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
permN := ptypes.PermFlag(Uint64FromWord256(permNum))
|
|
if err = vmAcc.Permissions.Base.Unset(permN); err != nil {
|
|
return nil, err
|
|
}
|
|
vm.appState.UpdateAccount(vmAcc)
|
|
return permNum.Bytes(), nil
|
|
}
|
|
|
|
func (vm *VM) setGlobalPerm(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("setGlobalPerm() takes three arguments (permission number, permission value)")
|
|
}
|
|
var permNum, perm Word256
|
|
copy(permNum[:], args[32:64])
|
|
copy(perm[:], args[64:96])
|
|
vmAcc := vm.appState.GetAccount(ptypes.GlobalPermissionsAddress256)
|
|
if vmAcc == nil {
|
|
panic("cant find the global permissions account")
|
|
}
|
|
permN := ptypes.PermFlag(Uint64FromWord256(permNum))
|
|
permV := !perm.IsZero()
|
|
if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
|
|
return nil, err
|
|
}
|
|
vm.appState.UpdateAccount(vmAcc)
|
|
return perm.Bytes(), nil
|
|
}
|
|
|
|
// TODO: needs access to an iterator ...
|
|
func (vm *VM) clearPerm(args []byte) (output []byte, err error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (vm *VM) hasRole(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
|
|
}
|
|
var addr, role Word256
|
|
copy(addr[:], args[32:64])
|
|
copy(role[:], args[64:96])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
roleS := string(role.Bytes())
|
|
var permInt byte
|
|
if vmAcc.Permissions.HasRole(roleS) {
|
|
permInt = 0x1
|
|
} else {
|
|
permInt = 0x0
|
|
}
|
|
return LeftPadWord256([]byte{permInt}).Bytes(), nil
|
|
}
|
|
|
|
func (vm *VM) addRole(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
|
|
}
|
|
var addr, role Word256
|
|
copy(addr[:], args[32:64])
|
|
copy(role[:], args[64:96])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
roleS := string(role.Bytes())
|
|
var permInt byte
|
|
if vmAcc.Permissions.AddRole(roleS) {
|
|
permInt = 0x1
|
|
} else {
|
|
permInt = 0x0
|
|
}
|
|
return LeftPadWord256([]byte{permInt}).Bytes(), nil
|
|
}
|
|
|
|
func (vm *VM) rmRole(args []byte) (output []byte, err error) {
|
|
if len(args) != 2*32 {
|
|
return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
|
|
}
|
|
var addr, role Word256
|
|
copy(addr[:], args[32:64])
|
|
copy(role[:], args[64:96])
|
|
vmAcc := vm.appState.GetAccount(addr)
|
|
if vmAcc == nil {
|
|
return nil, fmt.Errorf("Unknown account %X", addr)
|
|
}
|
|
roleS := string(role.Bytes())
|
|
var permInt byte
|
|
if vmAcc.Permissions.RmRole(roleS) {
|
|
permInt = 0x1
|
|
} else {
|
|
permInt = 0x0
|
|
}
|
|
return LeftPadWord256([]byte{permInt}).Bytes(), nil
|
|
}
|