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.

290 lines
6.9 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package types
  2. import (
  3. "fmt"
  4. . "github.com/tendermint/tendermint/common"
  5. "reflect"
  6. )
  7. //------------------------------------------------------------------------------------------------
  8. var (
  9. GlobalPermissionsAddress = Zero256[:20]
  10. GlobalPermissionsAddress256 = Zero256
  11. DougAddress = append([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []byte("THISISDOUG")...)
  12. DougAddress256 = LeftPadWord256(DougAddress)
  13. )
  14. // A particular permission
  15. type PermFlag uint64
  16. // Base permission references are like unix (the index is already bit shifted)
  17. const (
  18. Root PermFlag = 1 << iota // 1
  19. Send // 2
  20. Call // 4
  21. CreateContract // 8
  22. CreateAccount // 16
  23. Bond // 32
  24. Name // 64
  25. DefaultBBPB = Send | Call | CreateContract | CreateAccount | Bond | Name
  26. // XXX: must be adjusted if base perms added/removed
  27. NumBasePermissions uint = 7
  28. TopBasePermission PermFlag = 1 << (NumBasePermissions - 1)
  29. AllBasePermissions PermFlag = TopBasePermission | (TopBasePermission - 1)
  30. AllSet PermFlag = AllBasePermissions | AllSNativePermissions
  31. )
  32. // should have same ordering as above
  33. type BasePermissionsString struct {
  34. Root bool `json:"root,omitempty"`
  35. Send bool `json:"send,omitempty"`
  36. Call bool `json:"call,omitempty"`
  37. CreateContract bool `json:"create_contract,omitempty"`
  38. CreateAccount bool `json:"create_account,omitempty"`
  39. Bond bool `json:"bond,omitempty"`
  40. Name bool `json:"name,omitempty"`
  41. }
  42. //---------------------------------------------------------------------------------------------
  43. // Base chain permissions struct
  44. type BasePermissions struct {
  45. // bit array with "has"/"doesn't have" for each permission
  46. Perms PermFlag `json:"perms"`
  47. // bit array with "set"/"not set" for each permission (not-set should fall back to global)
  48. SetBit PermFlag `json:"set"`
  49. }
  50. func NewBasePermissions() *BasePermissions {
  51. return &BasePermissions{0, 0}
  52. }
  53. // Get a permission value. ty should be a power of 2.
  54. // ErrValueNotSet is returned if the permission's set bit is off,
  55. // and should be caught by caller so the global permission can be fetched
  56. func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
  57. if ty == 0 {
  58. return false, ErrInvalidPermission(ty)
  59. }
  60. if p.SetBit&ty == 0 {
  61. return false, ErrValueNotSet(ty)
  62. }
  63. return p.Perms&ty > 0, nil
  64. }
  65. // Set a permission bit. Will set the permission's set bit to true.
  66. func (p *BasePermissions) Set(ty PermFlag, value bool) error {
  67. if ty == 0 {
  68. return ErrInvalidPermission(ty)
  69. }
  70. p.SetBit |= ty
  71. if value {
  72. p.Perms |= ty
  73. } else {
  74. p.Perms &= ^ty
  75. }
  76. return nil
  77. }
  78. // Set the permission's set bit to false
  79. func (p *BasePermissions) Unset(ty PermFlag) error {
  80. if ty == 0 {
  81. return ErrInvalidPermission(ty)
  82. }
  83. p.SetBit &= ^ty
  84. return nil
  85. }
  86. // Check if the permission is set
  87. func (p *BasePermissions) IsSet(ty PermFlag) bool {
  88. if ty == 0 {
  89. return false
  90. }
  91. return p.SetBit&ty > 0
  92. }
  93. func (p *BasePermissions) Copy() *BasePermissions {
  94. if p == nil {
  95. return nil
  96. }
  97. return &BasePermissions{
  98. Perms: p.Perms,
  99. SetBit: p.SetBit,
  100. }
  101. }
  102. func (p *BasePermissions) String() string {
  103. return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
  104. }
  105. //---------------------------------------------------------------------------------------------
  106. type AccountPermissions struct {
  107. Base *BasePermissions `json:"base"`
  108. Roles []string `json:"roles"`
  109. }
  110. func NewAccountPermissions() *AccountPermissions {
  111. return &AccountPermissions{
  112. Base: NewBasePermissions(),
  113. Roles: []string{},
  114. }
  115. }
  116. // Returns true if the role is found
  117. func (aP *AccountPermissions) HasRole(role string) bool {
  118. role = string(LeftPadBytes([]byte(role), 32))
  119. for _, r := range aP.Roles {
  120. if r == role {
  121. return true
  122. }
  123. }
  124. return false
  125. }
  126. // Returns true if the role is added, and false if it already exists
  127. func (aP *AccountPermissions) AddRole(role string) bool {
  128. role = string(LeftPadBytes([]byte(role), 32))
  129. for _, r := range aP.Roles {
  130. if r == role {
  131. return false
  132. }
  133. }
  134. aP.Roles = append(aP.Roles, role)
  135. return true
  136. }
  137. // Returns true if the role is removed, and false if it is not found
  138. func (aP *AccountPermissions) RmRole(role string) bool {
  139. role = string(LeftPadBytes([]byte(role), 32))
  140. for i, r := range aP.Roles {
  141. if r == role {
  142. post := []string{}
  143. if len(aP.Roles) > i+1 {
  144. post = aP.Roles[i+1:]
  145. }
  146. aP.Roles = append(aP.Roles[:i], post...)
  147. return true
  148. }
  149. }
  150. return false
  151. }
  152. func (aP *AccountPermissions) Copy() *AccountPermissions {
  153. if aP == nil {
  154. return nil
  155. }
  156. r := make([]string, len(aP.Roles))
  157. copy(r, aP.Roles)
  158. return &AccountPermissions{
  159. Base: aP.Base.Copy(),
  160. Roles: r,
  161. }
  162. }
  163. func NewDefaultAccountPermissions() *AccountPermissions {
  164. return &AccountPermissions{
  165. Base: &BasePermissions{
  166. Perms: DefaultBBPB,
  167. SetBit: AllSet,
  168. },
  169. Roles: []string{},
  170. }
  171. }
  172. //---------------------------------------------------------------------------------------------
  173. // Utilities to make bitmasks human readable
  174. func NewDefaultAccountPermissionsString() BasePermissionsString {
  175. return BasePermissionsString{
  176. Root: false,
  177. Bond: true,
  178. Send: true,
  179. Call: true,
  180. Name: true,
  181. CreateAccount: true,
  182. CreateContract: true,
  183. }
  184. }
  185. func AccountPermissionsFromStrings(perms *BasePermissionsString, roles []string) (*AccountPermissions, error) {
  186. base := NewBasePermissions()
  187. permRv := reflect.ValueOf(perms)
  188. for i := uint(0); i < uint(permRv.NumField()); i++ {
  189. v := permRv.Field(int(i)).Bool()
  190. base.Set(1<<i, v)
  191. }
  192. aP := &AccountPermissions{
  193. Base: base,
  194. Roles: make([]string, len(roles)),
  195. }
  196. copy(aP.Roles, roles)
  197. return aP, nil
  198. }
  199. func AccountPermissionsToStrings(aP *AccountPermissions) (*BasePermissionsString, []string, error) {
  200. perms := new(BasePermissionsString)
  201. permsRv := reflect.ValueOf(perms).Elem()
  202. for i := uint(0); i < NumBasePermissions; i++ {
  203. pf := PermFlag(1 << i)
  204. if aP.Base.IsSet(pf) {
  205. // won't err if the bit is set
  206. v, _ := aP.Base.Get(pf)
  207. f := permsRv.Field(int(i))
  208. f.SetBool(v)
  209. }
  210. }
  211. roles := make([]string, len(aP.Roles))
  212. copy(roles, aP.Roles)
  213. return perms, roles, nil
  214. }
  215. func PermFlagToString(pf PermFlag) (perm string, err error) {
  216. switch pf {
  217. case Root:
  218. perm = "root"
  219. case Send:
  220. perm = "send"
  221. case Call:
  222. perm = "call"
  223. case CreateContract:
  224. perm = "create_contract"
  225. case CreateAccount:
  226. perm = "create_account"
  227. case Bond:
  228. perm = "bond"
  229. case Name:
  230. perm = "name"
  231. default:
  232. err = fmt.Errorf("Unknown permission flag %b", pf)
  233. }
  234. return
  235. }
  236. func PermStringToFlag(perm string) (pf PermFlag, err error) {
  237. switch perm {
  238. case "root":
  239. pf = Root
  240. case "send":
  241. pf = Send
  242. case "call":
  243. pf = Call
  244. case "create_contract":
  245. pf = CreateContract
  246. case "create_account":
  247. pf = CreateAccount
  248. case "bond":
  249. pf = Bond
  250. case "name":
  251. pf = Name
  252. default:
  253. err = fmt.Errorf("Unknown permission %s", perm)
  254. }
  255. return
  256. }