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.

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