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.

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