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.

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