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.

233 lines
7.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
  1. package vm
  2. import (
  3. "fmt"
  4. . "github.com/tendermint/go-common"
  5. ptypes "github.com/tendermint/tendermint/permission/types"
  6. )
  7. // TODO: ABI
  8. //------------------------------------------------------------------------------------------------
  9. // Registered SNative contracts
  10. func registerSNativeContracts() {
  11. registeredNativeContracts[LeftPadWord256([]byte("has_base"))] = hasBasePerm
  12. registeredNativeContracts[LeftPadWord256([]byte("set_base"))] = setBasePerm
  13. registeredNativeContracts[LeftPadWord256([]byte("unset_base"))] = unsetBasePerm
  14. registeredNativeContracts[LeftPadWord256([]byte("set_global"))] = setGlobalPerm
  15. registeredNativeContracts[LeftPadWord256([]byte("has_role"))] = hasRole
  16. registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = addRole
  17. registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rmRole
  18. }
  19. //-----------------------------------------------------------------------------
  20. // snative are native contracts that can access and modify an account's permissions
  21. // TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
  22. func hasBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  23. if !HasPermission(appState, caller, ptypes.HasBase) {
  24. return nil, ErrInvalidPermission{caller.Address, "has_base"}
  25. }
  26. if len(args) != 2*32 {
  27. return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permFlag)")
  28. }
  29. addr, permNum := returnTwoArgs(args)
  30. vmAcc := appState.GetAccount(addr)
  31. if vmAcc == nil {
  32. return nil, fmt.Errorf("Unknown account %X", addr)
  33. }
  34. permN := ptypes.PermFlag(Uint64FromWord256(permNum)) // already shifted
  35. if !ValidPermN(permN) {
  36. return nil, ptypes.ErrInvalidPermission(permN)
  37. }
  38. var permInt byte
  39. if HasPermission(appState, vmAcc, permN) {
  40. permInt = 0x1
  41. } else {
  42. permInt = 0x0
  43. }
  44. dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt)
  45. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  46. }
  47. func setBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  48. if !HasPermission(appState, caller, ptypes.SetBase) {
  49. return nil, ErrInvalidPermission{caller.Address, "set_base"}
  50. }
  51. if len(args) != 3*32 {
  52. return nil, fmt.Errorf("setBase() takes three arguments (address, permFlag, permission value)")
  53. }
  54. addr, permNum, perm := returnThreeArgs(args)
  55. vmAcc := appState.GetAccount(addr)
  56. if vmAcc == nil {
  57. return nil, fmt.Errorf("Unknown account %X", addr)
  58. }
  59. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  60. if !ValidPermN(permN) {
  61. return nil, ptypes.ErrInvalidPermission(permN)
  62. }
  63. permV := !perm.IsZero()
  64. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  65. return nil, err
  66. }
  67. appState.UpdateAccount(vmAcc)
  68. dbg.Printf("snative.setBasePerm(0x%X, %b, %v)\n", addr.Postfix(20), permN, permV)
  69. return perm.Bytes(), nil
  70. }
  71. func unsetBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  72. if !HasPermission(appState, caller, ptypes.UnsetBase) {
  73. return nil, ErrInvalidPermission{caller.Address, "unset_base"}
  74. }
  75. if len(args) != 2*32 {
  76. return nil, fmt.Errorf("unsetBase() takes two arguments (address, permFlag)")
  77. }
  78. addr, permNum := returnTwoArgs(args)
  79. vmAcc := appState.GetAccount(addr)
  80. if vmAcc == nil {
  81. return nil, fmt.Errorf("Unknown account %X", addr)
  82. }
  83. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  84. if !ValidPermN(permN) {
  85. return nil, ptypes.ErrInvalidPermission(permN)
  86. }
  87. if err = vmAcc.Permissions.Base.Unset(permN); err != nil {
  88. return nil, err
  89. }
  90. appState.UpdateAccount(vmAcc)
  91. dbg.Printf("snative.unsetBasePerm(0x%X, %b)\n", addr.Postfix(20), permN)
  92. return permNum.Bytes(), nil
  93. }
  94. func setGlobalPerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  95. if !HasPermission(appState, caller, ptypes.SetGlobal) {
  96. return nil, ErrInvalidPermission{caller.Address, "set_global"}
  97. }
  98. if len(args) != 2*32 {
  99. return nil, fmt.Errorf("setGlobal() takes two arguments (permFlag, permission value)")
  100. }
  101. permNum, perm := returnTwoArgs(args)
  102. vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256)
  103. if vmAcc == nil {
  104. PanicSanity("cant find the global permissions account")
  105. }
  106. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  107. if !ValidPermN(permN) {
  108. return nil, ptypes.ErrInvalidPermission(permN)
  109. }
  110. permV := !perm.IsZero()
  111. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  112. return nil, err
  113. }
  114. appState.UpdateAccount(vmAcc)
  115. dbg.Printf("snative.setGlobalPerm(%b, %v)\n", permN, permV)
  116. return perm.Bytes(), nil
  117. }
  118. func hasRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  119. if !HasPermission(appState, caller, ptypes.HasRole) {
  120. return nil, ErrInvalidPermission{caller.Address, "has_role"}
  121. }
  122. if len(args) != 2*32 {
  123. return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
  124. }
  125. addr, role := returnTwoArgs(args)
  126. vmAcc := appState.GetAccount(addr)
  127. if vmAcc == nil {
  128. return nil, fmt.Errorf("Unknown account %X", addr)
  129. }
  130. roleS := string(role.Bytes())
  131. var permInt byte
  132. if vmAcc.Permissions.HasRole(roleS) {
  133. permInt = 0x1
  134. } else {
  135. permInt = 0x0
  136. }
  137. dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  138. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  139. }
  140. func addRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  141. if !HasPermission(appState, caller, ptypes.AddRole) {
  142. return nil, ErrInvalidPermission{caller.Address, "add_role"}
  143. }
  144. if len(args) != 2*32 {
  145. return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
  146. }
  147. addr, role := returnTwoArgs(args)
  148. vmAcc := appState.GetAccount(addr)
  149. if vmAcc == nil {
  150. return nil, fmt.Errorf("Unknown account %X", addr)
  151. }
  152. roleS := string(role.Bytes())
  153. var permInt byte
  154. if vmAcc.Permissions.AddRole(roleS) {
  155. permInt = 0x1
  156. } else {
  157. permInt = 0x0
  158. }
  159. appState.UpdateAccount(vmAcc)
  160. dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  161. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  162. }
  163. func rmRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) {
  164. if !HasPermission(appState, caller, ptypes.RmRole) {
  165. return nil, ErrInvalidPermission{caller.Address, "rm_role"}
  166. }
  167. if len(args) != 2*32 {
  168. return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
  169. }
  170. addr, role := returnTwoArgs(args)
  171. vmAcc := appState.GetAccount(addr)
  172. if vmAcc == nil {
  173. return nil, fmt.Errorf("Unknown account %X", addr)
  174. }
  175. roleS := string(role.Bytes())
  176. var permInt byte
  177. if vmAcc.Permissions.RmRole(roleS) {
  178. permInt = 0x1
  179. } else {
  180. permInt = 0x0
  181. }
  182. appState.UpdateAccount(vmAcc)
  183. dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0)
  184. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  185. }
  186. //------------------------------------------------------------------------------------------------
  187. // Errors and utility funcs
  188. type ErrInvalidPermission struct {
  189. Address Word256
  190. SNative string
  191. }
  192. func (e ErrInvalidPermission) Error() string {
  193. return fmt.Sprintf("Account %X does not have permission snative.%s", e.Address.Postfix(20), e.SNative)
  194. }
  195. // Checks if a permission flag is valid (a known base chain or snative permission)
  196. func ValidPermN(n ptypes.PermFlag) bool {
  197. if n > ptypes.TopPermFlag {
  198. return false
  199. }
  200. return true
  201. }
  202. // CONTRACT: length has already been checked
  203. func returnTwoArgs(args []byte) (a Word256, b Word256) {
  204. copy(a[:], args[:32])
  205. copy(b[:], args[32:64])
  206. return
  207. }
  208. // CONTRACT: length has already been checked
  209. func returnThreeArgs(args []byte) (a Word256, b Word256, c Word256) {
  210. copy(a[:], args[:32])
  211. copy(b[:], args[32:64])
  212. copy(c[:], args[64:96])
  213. return
  214. }