/accounts/abi/type.go

https://gitlab.com/akomba/ether-bot-wallet · Go · 216 lines · 159 code · 16 blank · 41 comment · 46 complexity · 29f7f2045704bfb118a6ea91912c14dc MD5 · raw file

  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package abi
  17. import (
  18. "fmt"
  19. "reflect"
  20. "regexp"
  21. "strconv"
  22. "github.com/ethereum/go-ethereum/common"
  23. )
  24. const (
  25. IntTy byte = iota
  26. UintTy
  27. BoolTy
  28. SliceTy
  29. AddressTy
  30. RealTy
  31. )
  32. // Type is the reflection of the supported argument type
  33. type Type struct {
  34. Kind reflect.Kind
  35. Type reflect.Type
  36. Size int
  37. T byte // Our own type checking
  38. stringKind string // holds the unparsed string for deriving signatures
  39. }
  40. // NewType returns a fully parsed Type given by the input string or an error if it can't be parsed.
  41. //
  42. // Strings can be in the format of:
  43. //
  44. // Input = Type [ "[" [ Number ] "]" ] Name .
  45. // Type = [ "u" ] "int" [ Number ] .
  46. //
  47. // Examples:
  48. //
  49. // string int uint real
  50. // string32 int8 uint8 uint[]
  51. // address int256 uint256 real[2]
  52. func NewType(t string) (typ Type, err error) {
  53. // 1. full string 2. type 3. (opt.) is slice 4. (opt.) size
  54. freg, err := regexp.Compile("([a-zA-Z0-9]+)(\\[([0-9]*)?\\])?")
  55. if err != nil {
  56. return Type{}, err
  57. }
  58. res := freg.FindAllStringSubmatch(t, -1)[0]
  59. var (
  60. isslice bool
  61. size int
  62. )
  63. switch {
  64. case res[3] != "":
  65. // err is ignored. Already checked for number through the regexp
  66. size, _ = strconv.Atoi(res[3])
  67. isslice = true
  68. case res[2] != "":
  69. isslice = true
  70. size = -1
  71. case res[0] == "":
  72. return Type{}, fmt.Errorf("type parse error for `%s`", t)
  73. }
  74. treg, err := regexp.Compile("([a-zA-Z]+)([0-9]*)?")
  75. if err != nil {
  76. return Type{}, err
  77. }
  78. parsedType := treg.FindAllStringSubmatch(res[1], -1)[0]
  79. vsize, _ := strconv.Atoi(parsedType[2])
  80. vtype := parsedType[1]
  81. // substitute canonical representation
  82. if vsize == 0 && (vtype == "int" || vtype == "uint") {
  83. vsize = 256
  84. t += "256"
  85. }
  86. if isslice {
  87. typ.Kind = reflect.Slice
  88. typ.Size = size
  89. switch vtype {
  90. case "int":
  91. typ.Type = big_ts
  92. case "uint":
  93. typ.Type = ubig_ts
  94. default:
  95. return Type{}, fmt.Errorf("unsupported arg slice type: %s", t)
  96. }
  97. } else {
  98. switch vtype {
  99. case "int":
  100. typ.Kind = reflect.Ptr
  101. typ.Type = big_t
  102. typ.Size = 256
  103. typ.T = IntTy
  104. case "uint":
  105. typ.Kind = reflect.Ptr
  106. typ.Type = ubig_t
  107. typ.Size = 256
  108. typ.T = UintTy
  109. case "bool":
  110. typ.Kind = reflect.Bool
  111. case "real": // TODO
  112. typ.Kind = reflect.Invalid
  113. case "address":
  114. typ.Kind = reflect.Slice
  115. typ.Type = byte_ts
  116. typ.Size = 20
  117. typ.T = AddressTy
  118. case "string":
  119. typ.Kind = reflect.String
  120. typ.Size = -1
  121. if vsize > 0 {
  122. typ.Size = 32
  123. }
  124. case "bytes":
  125. typ.Kind = reflect.Slice
  126. typ.Type = byte_ts
  127. typ.Size = vsize
  128. default:
  129. return Type{}, fmt.Errorf("unsupported arg type: %s", t)
  130. }
  131. }
  132. typ.stringKind = t
  133. return
  134. }
  135. func (t Type) String() (out string) {
  136. return t.stringKind
  137. }
  138. // Test the given input parameter `v` and checks if it matches certain
  139. // criteria
  140. // * Big integers are checks for ptr types and if the given value is
  141. // assignable
  142. // * Integer are checked for size
  143. // * Strings, addresses and bytes are checks for type and size
  144. func (t Type) pack(v interface{}) ([]byte, error) {
  145. value := reflect.ValueOf(v)
  146. switch kind := value.Kind(); kind {
  147. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  148. if t.Type != ubig_t {
  149. return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v)
  150. }
  151. return packNum(value, t.T), nil
  152. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  153. if t.Type != ubig_t {
  154. return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v)
  155. }
  156. return packNum(value, t.T), nil
  157. case reflect.Ptr:
  158. // If the value is a ptr do a assign check (only used by
  159. // big.Int for now)
  160. if t.Type == ubig_t && value.Type() != ubig_t {
  161. return nil, fmt.Errorf("type mismatch: %s for %T", t.Type, v)
  162. }
  163. return packNum(value, t.T), nil
  164. case reflect.String:
  165. if t.Size > -1 && value.Len() > t.Size {
  166. return nil, fmt.Errorf("%v out of bound. %d for %d", value.Kind(), value.Len(), t.Size)
  167. }
  168. return []byte(common.LeftPadString(t.String(), 32)), nil
  169. case reflect.Slice:
  170. if t.Size > -1 && value.Len() > t.Size {
  171. return nil, fmt.Errorf("%v out of bound. %d for %d", value.Kind(), value.Len(), t.Size)
  172. }
  173. // Address is a special slice. The slice acts as one rather than a list of elements.
  174. if t.T == AddressTy {
  175. return common.LeftPadBytes(v.([]byte), 32), nil
  176. }
  177. // Signed / Unsigned check
  178. if (t.T != IntTy && isSigned(value)) || (t.T == UintTy && isSigned(value)) {
  179. return nil, fmt.Errorf("slice of incompatible types.")
  180. }
  181. var packed []byte
  182. for i := 0; i < value.Len(); i++ {
  183. packed = append(packed, packNum(value.Index(i), t.T)...)
  184. }
  185. return packed, nil
  186. case reflect.Bool:
  187. if value.Bool() {
  188. return common.LeftPadBytes(common.Big1.Bytes(), 32), nil
  189. } else {
  190. return common.LeftPadBytes(common.Big0.Bytes(), 32), nil
  191. }
  192. case reflect.Array:
  193. if v, ok := value.Interface().(common.Address); ok {
  194. return t.pack(v[:])
  195. } else if v, ok := value.Interface().(common.Hash); ok {
  196. return t.pack(v[:])
  197. }
  198. }
  199. return nil, fmt.Errorf("ABI: bad input given %T", value.Kind())
  200. }