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.

165 lines
4.7 KiB

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. type SNativeContract func(input []byte) (output []byte, err error)
  8. //-----------------------------------------------------------------------------
  9. // snative are native contracts that can access and manipulate the chain state
  10. // (in particular the permissions values)
  11. // TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?)
  12. func (vm *VM) hasBasePerm(args []byte) (output []byte, err error) {
  13. if len(args) != 2*32 {
  14. return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permission number)")
  15. }
  16. var addr, permNum Word256
  17. copy(addr[:], args[:32])
  18. copy(permNum[:], args[32:64])
  19. vmAcc := vm.appState.GetAccount(addr)
  20. if vmAcc == nil {
  21. return nil, fmt.Errorf("Unknown account %X", addr)
  22. }
  23. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  24. var permInt byte
  25. if vm.HasPermission(vmAcc, permN) {
  26. permInt = 0x1
  27. } else {
  28. permInt = 0x0
  29. }
  30. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  31. }
  32. func (vm *VM) setBasePerm(args []byte) (output []byte, err error) {
  33. if len(args) != 3*32 {
  34. return nil, fmt.Errorf("setBasePerm() takes three arguments (address, permission number, permission value)")
  35. }
  36. var addr, permNum, perm Word256
  37. copy(addr[:], args[:32])
  38. copy(permNum[:], args[32:64])
  39. copy(perm[:], args[64:96])
  40. vmAcc := vm.appState.GetAccount(addr)
  41. if vmAcc == nil {
  42. return nil, fmt.Errorf("Unknown account %X", addr)
  43. }
  44. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  45. permV := !perm.IsZero()
  46. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  47. return nil, err
  48. }
  49. vm.appState.UpdateAccount(vmAcc)
  50. return perm.Bytes(), nil
  51. }
  52. func (vm *VM) unsetBasePerm(args []byte) (output []byte, err error) {
  53. if len(args) != 2*32 {
  54. return nil, fmt.Errorf("unsetBasePerm() takes two arguments (address, permission number)")
  55. }
  56. var addr, permNum Word256
  57. copy(addr[:], args[:32])
  58. copy(permNum[:], args[32:64])
  59. vmAcc := vm.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 err = vmAcc.Permissions.Base.Unset(permN); err != nil {
  65. return nil, err
  66. }
  67. vm.appState.UpdateAccount(vmAcc)
  68. return permNum.Bytes(), nil
  69. }
  70. func (vm *VM) setGlobalPerm(args []byte) (output []byte, err error) {
  71. if len(args) != 2*32 {
  72. return nil, fmt.Errorf("setGlobalPerm() takes three arguments (permission number, permission value)")
  73. }
  74. var permNum, perm Word256
  75. copy(permNum[:], args[32:64])
  76. copy(perm[:], args[64:96])
  77. vmAcc := vm.appState.GetAccount(ptypes.GlobalPermissionsAddress256)
  78. if vmAcc == nil {
  79. panic("cant find the global permissions account")
  80. }
  81. permN := ptypes.PermFlag(Uint64FromWord256(permNum))
  82. permV := !perm.IsZero()
  83. if err = vmAcc.Permissions.Base.Set(permN, permV); err != nil {
  84. return nil, err
  85. }
  86. vm.appState.UpdateAccount(vmAcc)
  87. return perm.Bytes(), nil
  88. }
  89. // TODO: needs access to an iterator ...
  90. func (vm *VM) clearPerm(args []byte) (output []byte, err error) {
  91. return nil, nil
  92. }
  93. func (vm *VM) hasRole(args []byte) (output []byte, err error) {
  94. if len(args) != 2*32 {
  95. return nil, fmt.Errorf("hasRole() takes two arguments (address, role)")
  96. }
  97. var addr, role Word256
  98. copy(addr[:], args[32:64])
  99. copy(role[:], args[64:96])
  100. vmAcc := vm.appState.GetAccount(addr)
  101. if vmAcc == nil {
  102. return nil, fmt.Errorf("Unknown account %X", addr)
  103. }
  104. roleS := string(role.Bytes())
  105. var permInt byte
  106. if vmAcc.Permissions.HasRole(roleS) {
  107. permInt = 0x1
  108. } else {
  109. permInt = 0x0
  110. }
  111. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  112. }
  113. func (vm *VM) addRole(args []byte) (output []byte, err error) {
  114. if len(args) != 2*32 {
  115. return nil, fmt.Errorf("addRole() takes two arguments (address, role)")
  116. }
  117. var addr, role Word256
  118. copy(addr[:], args[32:64])
  119. copy(role[:], args[64:96])
  120. vmAcc := vm.appState.GetAccount(addr)
  121. if vmAcc == nil {
  122. return nil, fmt.Errorf("Unknown account %X", addr)
  123. }
  124. roleS := string(role.Bytes())
  125. var permInt byte
  126. if vmAcc.Permissions.AddRole(roleS) {
  127. permInt = 0x1
  128. } else {
  129. permInt = 0x0
  130. }
  131. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  132. }
  133. func (vm *VM) rmRole(args []byte) (output []byte, err error) {
  134. if len(args) != 2*32 {
  135. return nil, fmt.Errorf("rmRole() takes two arguments (address, role)")
  136. }
  137. var addr, role Word256
  138. copy(addr[:], args[32:64])
  139. copy(role[:], args[64:96])
  140. vmAcc := vm.appState.GetAccount(addr)
  141. if vmAcc == nil {
  142. return nil, fmt.Errorf("Unknown account %X", addr)
  143. }
  144. roleS := string(role.Bytes())
  145. var permInt byte
  146. if vmAcc.Permissions.RmRole(roleS) {
  147. permInt = 0x1
  148. } else {
  149. permInt = 0x0
  150. }
  151. return LeftPadWord256([]byte{permInt}).Bytes(), nil
  152. }