You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
8.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package vm
  2. import (
  3. "fmt"
  4. . "github.com/tendermint/tendermint/common"
  5. ptypes "github.com/tendermint/tendermint/permission/types"
  6. )
  7. type ErrInvalidPermission struct {
  8. Address Word256
  9. SNative string
  10. }
  11. func (e ErrInvalidPermission) Error() string {
  12. return fmt.Sprintf("Account %X does not have permission snative.%s", e.Address.Postfix(20), e.SNative)
  13. }
  14. // Checks if a permission flag is valid (a known base chain or snative permission)
  15. func ValidPermN(n ptypes.PermFlag) bool {
  16. if n > ptypes.TopBasePermission && n < FirstSNativePerm {
  17. return false
  18. } else if n > TopSNativePermission {
  19. return false
  20. }
  21. return true
  22. }
  23. const (
  24. // first 32 bits of BasePermission are for chain, second 32 are for snative
  25. FirstSNativePerm ptypes.PermFlag = 1 << 32
  26. // each snative has an associated permission flag
  27. HasBasePerm ptypes.PermFlag = FirstSNativePerm << iota
  28. SetBasePerm
  29. UnsetBasePerm
  30. SetGlobalPerm
  31. ClearBasePerm
  32. HasRole
  33. AddRole
  34. RmRole
  35. // XXX: must be adjusted if snative's added/removed
  36. NumSNativePermissions uint = 8
  37. TopSNativePermission ptypes.PermFlag = FirstSNativePerm << (NumSNativePermissions - 1)
  38. )
  39. var RegisteredSNativeContracts = map[Word256]ptypes.PermFlag{
  40. LeftPadWord256([]byte("hasBasePerm")): HasBasePerm,
  41. LeftPadWord256([]byte("setBasePerm")): SetBasePerm,
  42. LeftPadWord256([]byte("unsetBasePerm")): UnsetBasePerm,
  43. LeftPadWord256([]byte("setGlobalPerm")): SetGlobalPerm,
  44. LeftPadWord256([]byte("hasRole")): HasRole,
  45. LeftPadWord256([]byte("addRole")): AddRole,
  46. LeftPadWord256([]byte("rmRole")): RmRole,
  47. }
  48. // takes an account so it can check for permission to access the contract
  49. // NOTE: the account is the currently executing account (the callee), not say an origin caller
  50. type SNativeContract func(acc *Account, input []byte) (output []byte, err error)
  51. func (vm *VM) SNativeContract(name Word256) SNativeContract {
  52. flag := RegisteredSNativeContracts[name]
  53. switch flag {
  54. case HasBasePerm:
  55. return vm.hasBasePerm
  56. case SetBasePerm:
  57. return vm.setBasePerm
  58. case UnsetBasePerm:
  59. return vm.unsetBasePerm
  60. case SetGlobalPerm:
  61. return vm.setGlobalPerm
  62. case HasRole:
  63. return vm.hasRole
  64. case AddRole:
  65. return vm.addRole
  66. case RmRole:
  67. return vm.rmRole
  68. default:
  69. return nil
  70. }
  71. }
  72. //-----------------------------------------------------------------------------
  73. // snative are native contracts that can access and manipulate the chain state
  74. // (in particular the permissions values)
  75. // TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
  76. func (vm *VM) hasBasePerm(acc *Account, args []byte) (output []byte, err error) {
  77. if !vm.HasPermission(acc, HasBasePerm) {
  78. return nil, ErrInvalidPermission{acc.Address, "HasBasePerm"}
  79. }
  80. if len(args) != 2*32 {
  81. return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permission number)")
  82. }
  83. var addr, permNum Word256
  84. copy(addr[:], args[:32])
  85. copy(permNum[:], args[32:64])
  86. vmAcc := vm.appState.GetAccount(addr)
  87. if vmAcc == nil {
  88. return nil, fmt.Errorf("Unknown account %X", addr)
  89. }
  90. permN := ptypes.PermFlag(Uint64FromWord256(permNum)) // already shifted
  91. if !ValidPermN(permN) {
  92. return nil, ptypes.ErrInvalidPermission(permN)
  93. }
  94. var permInt byte
  95. if vm.HasPermission(vmAcc, permN) {
  96. permInt = 0x1
  97. } else {
  98. permInt = 0x0
  99. }
  100. dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt)
  101. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  102. }
  103. func (vm *VM) setBasePerm(acc *Account, args []byte) (output []byte, err error) {
  104. if !vm.HasPermission(acc, SetBasePerm) {
  105. return nil, ErrInvalidPermission{acc.Address, "SetBasePerm"}
  106. }
  107. if len(args) != 3*32 {
  108. return nil, fmt.Errorf("setBasePerm() takes three arguments (address, permission number, permission value)")
  109. }
  110. var addr, permNum, perm Word256
  111. copy(addr[:], args[:32])
  112. copy(permNum[:], args[32:64])
  113. copy(perm[:], args[64:96])
  114. vmAcc := vm.appState.GetAccount(addr)
  115. if vmAcc == nil {
  116. return nil, fmt.Errorf("Unknown account %X", addr)
  117. }
  118. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  119. if !ValidPermN(permN) {
  120. return nil, ptypes.ErrInvalidPermission(permN)
  121. }
  122. permV := !perm.IsZero()
  123. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  124. return nil, err
  125. }
  126. vm.appState.UpdateAccount(vmAcc)
  127. dbg.Printf("snative.setBasePerm(0x%X, %b, %v)\n", addr.Postfix(20), permN, permV)
  128. return perm.Bytes(), nil
  129. }
  130. func (vm *VM) unsetBasePerm(acc *Account, args []byte) (output []byte, err error) {
  131. if !vm.HasPermission(acc, UnsetBasePerm) {
  132. return nil, ErrInvalidPermission{acc.Address, "UnsetBasePerm"}
  133. }
  134. if len(args) != 2*32 {
  135. return nil, fmt.Errorf("unsetBasePerm() takes two arguments (address, permission number)")
  136. }
  137. var addr, permNum Word256
  138. copy(addr[:], args[:32])
  139. copy(permNum[:], args[32:64])
  140. vmAcc := vm.appState.GetAccount(addr)
  141. if vmAcc == nil {
  142. return nil, fmt.Errorf("Unknown account %X", addr)
  143. }
  144. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  145. if !ValidPermN(permN) {
  146. return nil, ptypes.ErrInvalidPermission(permN)
  147. }
  148. if err = vmAcc.Permissions.Base.Unset(permN); err != nil {
  149. return nil, err
  150. }
  151. vm.appState.UpdateAccount(vmAcc)
  152. dbg.Printf("snative.unsetBasePerm(0x%X, %b)\n", addr.Postfix(20), permN)
  153. return permNum.Bytes(), nil
  154. }
  155. func (vm *VM) setGlobalPerm(acc *Account, args []byte) (output []byte, err error) {
  156. if !vm.HasPermission(acc, SetGlobalPerm) {
  157. return nil, ErrInvalidPermission{acc.Address, "SetGlobalPerm"}
  158. }
  159. if len(args) != 2*32 {
  160. return nil, fmt.Errorf("setGlobalPerm() takes two arguments (permission number, permission value)")
  161. }
  162. var permNum, perm Word256
  163. copy(permNum[:], args[:32])
  164. copy(perm[:], args[32:64])
  165. vmAcc := vm.appState.GetAccount(ptypes.GlobalPermissionsAddress256)
  166. if vmAcc == nil {
  167. panic("cant find the global permissions account")
  168. }
  169. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  170. if !ValidPermN(permN) {
  171. return nil, ptypes.ErrInvalidPermission(permN)
  172. }
  173. permV := !perm.IsZero()
  174. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  175. return nil, err
  176. }
  177. vm.appState.UpdateAccount(vmAcc)
  178. dbg.Printf("snative.setGlobalPerm(%b, %v)\n", permN, permV)
  179. return perm.Bytes(), nil
  180. }
  181. // TODO: needs access to an iterator ...
  182. func (vm *VM) clearPerm(acc *Account, args []byte) (output []byte, err error) {
  183. if !vm.HasPermission(acc, ClearBasePerm) {
  184. return nil, ErrInvalidPermission{acc.Address, "ClearPerm"}
  185. }
  186. return nil, nil
  187. }
  188. func (vm *VM) hasRole(acc *Account, args []byte) (output []byte, err error) {
  189. if !vm.HasPermission(acc, HasRole) {
  190. return nil, ErrInvalidPermission{acc.Address, "HasRole"}
  191. }
  192. if len(args) != 2*32 {
  193. return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
  194. }
  195. var addr, role Word256
  196. copy(addr[:], args[:32])
  197. copy(role[:], args[32:64])
  198. vmAcc := vm.appState.GetAccount(addr)
  199. if vmAcc == nil {
  200. return nil, fmt.Errorf("Unknown account %X", addr)
  201. }
  202. roleS := string(role.Bytes())
  203. var permInt byte
  204. if vmAcc.Permissions.HasRole(roleS) {
  205. permInt = 0x1
  206. } else {
  207. permInt = 0x0
  208. }
  209. dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  210. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  211. }
  212. func (vm *VM) addRole(acc *Account, args []byte) (output []byte, err error) {
  213. if !vm.HasPermission(acc, AddRole) {
  214. return nil, ErrInvalidPermission{acc.Address, "AddRole"}
  215. }
  216. if len(args) != 2*32 {
  217. return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
  218. }
  219. var addr, role Word256
  220. copy(addr[:], args[:32])
  221. copy(role[:], args[32:64])
  222. vmAcc := vm.appState.GetAccount(addr)
  223. if vmAcc == nil {
  224. return nil, fmt.Errorf("Unknown account %X", addr)
  225. }
  226. roleS := string(role.Bytes())
  227. var permInt byte
  228. if vmAcc.Permissions.AddRole(roleS) {
  229. permInt = 0x1
  230. } else {
  231. permInt = 0x0
  232. }
  233. vm.appState.UpdateAccount(vmAcc)
  234. dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  235. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  236. }
  237. func (vm *VM) rmRole(acc *Account, args []byte) (output []byte, err error) {
  238. if !vm.HasPermission(acc, RmRole) {
  239. return nil, ErrInvalidPermission{acc.Address, "RmRole"}
  240. }
  241. if len(args) != 2*32 {
  242. return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
  243. }
  244. var addr, role Word256
  245. copy(addr[:], args[:32])
  246. copy(role[:], args[32:64])
  247. vmAcc := vm.appState.GetAccount(addr)
  248. if vmAcc == nil {
  249. return nil, fmt.Errorf("Unknown account %X", addr)
  250. }
  251. roleS := string(role.Bytes())
  252. var permInt byte
  253. if vmAcc.Permissions.RmRole(roleS) {
  254. permInt = 0x1
  255. } else {
  256. permInt = 0x0
  257. }
  258. vm.appState.UpdateAccount(vmAcc)
  259. dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  260. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  261. }