type.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. "errors"
  19. "fmt"
  20. "reflect"
  21. "regexp"
  22. "strconv"
  23. "strings"
  24. "unicode"
  25. "unicode/utf8"
  26. "github.com/ethereum/go-ethereum/common"
  27. )
  28. // Type enumerator
  29. const (
  30. IntTy byte = iota
  31. UintTy
  32. BoolTy
  33. StringTy
  34. SliceTy
  35. ArrayTy
  36. TupleTy
  37. AddressTy
  38. FixedBytesTy
  39. BytesTy
  40. HashTy
  41. FixedPointTy
  42. FunctionTy
  43. )
  44. // Type is the reflection of the supported argument type.
  45. type Type struct {
  46. Elem *Type
  47. Size int
  48. T byte // Our own type checking
  49. stringKind string // holds the unparsed string for deriving signatures
  50. // Tuple relative fields
  51. TupleRawName string // Raw struct name defined in source code, may be empty.
  52. TupleElems []*Type // Type information of all tuple fields
  53. TupleRawNames []string // Raw field name of all tuple fields
  54. TupleType reflect.Type // Underlying struct of the tuple
  55. }
  56. var (
  57. // typeRegex parses the abi sub types
  58. typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
  59. )
  60. // NewType creates a new reflection type of abi type given in t.
  61. func NewType(t string, internalType string, components []ArgumentMarshaling) (typ Type, err error) {
  62. // check that array brackets are equal if they exist
  63. if strings.Count(t, "[") != strings.Count(t, "]") {
  64. return Type{}, fmt.Errorf("invalid arg type in abi")
  65. }
  66. typ.stringKind = t
  67. // if there are brackets, get ready to go into slice/array mode and
  68. // recursively create the type
  69. if strings.Count(t, "[") != 0 {
  70. // Note internalType can be empty here.
  71. subInternal := internalType
  72. if i := strings.LastIndex(internalType, "["); i != -1 {
  73. subInternal = subInternal[:i]
  74. }
  75. // recursively embed the type
  76. i := strings.LastIndex(t, "[")
  77. embeddedType, err := NewType(t[:i], subInternal, components)
  78. if err != nil {
  79. return Type{}, err
  80. }
  81. // grab the last cell and create a type from there
  82. sliced := t[i:]
  83. // grab the slice size with regexp
  84. re := regexp.MustCompile("[0-9]+")
  85. intz := re.FindAllString(sliced, -1)
  86. if len(intz) == 0 {
  87. // is a slice
  88. typ.T = SliceTy
  89. typ.Elem = &embeddedType
  90. typ.stringKind = embeddedType.stringKind + sliced
  91. } else if len(intz) == 1 {
  92. // is an array
  93. typ.T = ArrayTy
  94. typ.Elem = &embeddedType
  95. typ.Size, err = strconv.Atoi(intz[0])
  96. if err != nil {
  97. return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
  98. }
  99. typ.stringKind = embeddedType.stringKind + sliced
  100. } else {
  101. return Type{}, fmt.Errorf("invalid formatting of array type")
  102. }
  103. return typ, err
  104. }
  105. // parse the type and size of the abi-type.
  106. matches := typeRegex.FindAllStringSubmatch(t, -1)
  107. if len(matches) == 0 {
  108. return Type{}, fmt.Errorf("invalid type '%v'", t)
  109. }
  110. parsedType := matches[0]
  111. // varSize is the size of the variable
  112. var varSize int
  113. if len(parsedType[3]) > 0 {
  114. var err error
  115. varSize, err = strconv.Atoi(parsedType[2])
  116. if err != nil {
  117. return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
  118. }
  119. } else {
  120. if parsedType[0] == "uint" || parsedType[0] == "int" {
  121. // this should fail because it means that there's something wrong with
  122. // the abi type (the compiler should always format it to the size...always)
  123. return Type{}, fmt.Errorf("unsupported arg type: %s", t)
  124. }
  125. }
  126. // varType is the parsed abi type
  127. switch varType := parsedType[1]; varType {
  128. case "int":
  129. typ.Size = varSize
  130. typ.T = IntTy
  131. case "uint":
  132. typ.Size = varSize
  133. typ.T = UintTy
  134. case "bool":
  135. typ.T = BoolTy
  136. case "address":
  137. typ.Size = 20
  138. typ.T = AddressTy
  139. case "string":
  140. typ.T = StringTy
  141. case "bytes":
  142. if varSize == 0 {
  143. typ.T = BytesTy
  144. } else {
  145. typ.T = FixedBytesTy
  146. typ.Size = varSize
  147. }
  148. case "tuple":
  149. var (
  150. fields []reflect.StructField
  151. elems []*Type
  152. names []string
  153. expression string // canonical parameter expression
  154. used = make(map[string]bool)
  155. )
  156. expression += "("
  157. for idx, c := range components {
  158. cType, err := NewType(c.Type, c.InternalType, c.Components)
  159. if err != nil {
  160. return Type{}, err
  161. }
  162. name := ToCamelCase(c.Name)
  163. if name == "" {
  164. return Type{}, errors.New("abi: purely anonymous or underscored field is not supported")
  165. }
  166. fieldName := ResolveNameConflict(name, func(s string) bool { return used[s] })
  167. if err != nil {
  168. return Type{}, err
  169. }
  170. used[fieldName] = true
  171. if !isValidFieldName(fieldName) {
  172. return Type{}, fmt.Errorf("field %d has invalid name", idx)
  173. }
  174. fields = append(fields, reflect.StructField{
  175. Name: fieldName, // reflect.StructOf will panic for any exported field.
  176. Type: cType.GetType(),
  177. Tag: reflect.StructTag("json:\"" + c.Name + "\""),
  178. })
  179. elems = append(elems, &cType)
  180. names = append(names, c.Name)
  181. expression += cType.stringKind
  182. if idx != len(components)-1 {
  183. expression += ","
  184. }
  185. }
  186. expression += ")"
  187. typ.TupleType = reflect.StructOf(fields)
  188. typ.TupleElems = elems
  189. typ.TupleRawNames = names
  190. typ.T = TupleTy
  191. typ.stringKind = expression
  192. const structPrefix = "struct "
  193. // After solidity 0.5.10, a new field of abi "internalType"
  194. // is introduced. From that we can obtain the struct name
  195. // user defined in the source code.
  196. if internalType != "" && strings.HasPrefix(internalType, structPrefix) {
  197. // Foo.Bar type definition is not allowed in golang,
  198. // convert the format to FooBar
  199. typ.TupleRawName = strings.ReplaceAll(internalType[len(structPrefix):], ".", "")
  200. }
  201. case "function":
  202. typ.T = FunctionTy
  203. typ.Size = 24
  204. default:
  205. return Type{}, fmt.Errorf("unsupported arg type: %s", t)
  206. }
  207. return
  208. }
  209. // GetType returns the reflection type of the ABI type.
  210. func (t Type) GetType() reflect.Type {
  211. switch t.T {
  212. case IntTy:
  213. return reflectIntType(false, t.Size)
  214. case UintTy:
  215. return reflectIntType(true, t.Size)
  216. case BoolTy:
  217. return reflect.TypeOf(false)
  218. case StringTy:
  219. return reflect.TypeOf("")
  220. case SliceTy:
  221. return reflect.SliceOf(t.Elem.GetType())
  222. case ArrayTy:
  223. return reflect.ArrayOf(t.Size, t.Elem.GetType())
  224. case TupleTy:
  225. return t.TupleType
  226. case AddressTy:
  227. return reflect.TypeOf(common.Address{})
  228. case FixedBytesTy:
  229. return reflect.ArrayOf(t.Size, reflect.TypeOf(byte(0)))
  230. case BytesTy:
  231. return reflect.SliceOf(reflect.TypeOf(byte(0)))
  232. case HashTy:
  233. // hashtype currently not used
  234. return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
  235. case FixedPointTy:
  236. // fixedpoint type currently not used
  237. return reflect.ArrayOf(32, reflect.TypeOf(byte(0)))
  238. case FunctionTy:
  239. return reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
  240. default:
  241. panic("Invalid type")
  242. }
  243. }
  244. // String implements Stringer.
  245. func (t Type) String() (out string) {
  246. return t.stringKind
  247. }
  248. func (t Type) pack(v reflect.Value) ([]byte, error) {
  249. // dereference pointer first if it's a pointer
  250. v = indirect(v)
  251. if err := typeCheck(t, v); err != nil {
  252. return nil, err
  253. }
  254. switch t.T {
  255. case SliceTy, ArrayTy:
  256. var ret []byte
  257. if t.requiresLengthPrefix() {
  258. // append length
  259. ret = append(ret, packNum(reflect.ValueOf(v.Len()))...)
  260. }
  261. // calculate offset if any
  262. offset := 0
  263. offsetReq := isDynamicType(*t.Elem)
  264. if offsetReq {
  265. offset = getTypeSize(*t.Elem) * v.Len()
  266. }
  267. var tail []byte
  268. for i := 0; i < v.Len(); i++ {
  269. val, err := t.Elem.pack(v.Index(i))
  270. if err != nil {
  271. return nil, err
  272. }
  273. if !offsetReq {
  274. ret = append(ret, val...)
  275. continue
  276. }
  277. ret = append(ret, packNum(reflect.ValueOf(offset))...)
  278. offset += len(val)
  279. tail = append(tail, val...)
  280. }
  281. return append(ret, tail...), nil
  282. case TupleTy:
  283. // (T1,...,Tk) for k >= 0 and any types T1, …, Tk
  284. // enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))
  285. // where X = (X(1), ..., X(k)) and head and tail are defined for Ti being a static
  286. // type as
  287. // head(X(i)) = enc(X(i)) and tail(X(i)) = "" (the empty string)
  288. // and as
  289. // head(X(i)) = enc(len(head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1))))
  290. // tail(X(i)) = enc(X(i))
  291. // otherwise, i.e. if Ti is a dynamic type.
  292. fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, v)
  293. if err != nil {
  294. return nil, err
  295. }
  296. // Calculate prefix occupied size.
  297. offset := 0
  298. for _, elem := range t.TupleElems {
  299. offset += getTypeSize(*elem)
  300. }
  301. var ret, tail []byte
  302. for i, elem := range t.TupleElems {
  303. field := v.FieldByName(fieldmap[t.TupleRawNames[i]])
  304. if !field.IsValid() {
  305. return nil, fmt.Errorf("field %s for tuple not found in the given struct", t.TupleRawNames[i])
  306. }
  307. val, err := elem.pack(field)
  308. if err != nil {
  309. return nil, err
  310. }
  311. if isDynamicType(*elem) {
  312. ret = append(ret, packNum(reflect.ValueOf(offset))...)
  313. tail = append(tail, val...)
  314. offset += len(val)
  315. } else {
  316. ret = append(ret, val...)
  317. }
  318. }
  319. return append(ret, tail...), nil
  320. default:
  321. return packElement(t, v)
  322. }
  323. }
  324. // requireLengthPrefix returns whether the type requires any sort of length
  325. // prefixing.
  326. func (t Type) requiresLengthPrefix() bool {
  327. return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
  328. }
  329. // isDynamicType returns true if the type is dynamic.
  330. // The following types are called “dynamic”:
  331. // * bytes
  332. // * string
  333. // * T[] for any T
  334. // * T[k] for any dynamic T and any k >= 0
  335. // * (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k
  336. func isDynamicType(t Type) bool {
  337. if t.T == TupleTy {
  338. for _, elem := range t.TupleElems {
  339. if isDynamicType(*elem) {
  340. return true
  341. }
  342. }
  343. return false
  344. }
  345. return t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && isDynamicType(*t.Elem))
  346. }
  347. // getTypeSize returns the size that this type needs to occupy.
  348. // We distinguish static and dynamic types. Static types are encoded in-place
  349. // and dynamic types are encoded at a separately allocated location after the
  350. // current block.
  351. // So for a static variable, the size returned represents the size that the
  352. // variable actually occupies.
  353. // For a dynamic variable, the returned size is fixed 32 bytes, which is used
  354. // to store the location reference for actual value storage.
  355. func getTypeSize(t Type) int {
  356. if t.T == ArrayTy && !isDynamicType(*t.Elem) {
  357. // Recursively calculate type size if it is a nested array
  358. if t.Elem.T == ArrayTy || t.Elem.T == TupleTy {
  359. return t.Size * getTypeSize(*t.Elem)
  360. }
  361. return t.Size * 32
  362. } else if t.T == TupleTy && !isDynamicType(t) {
  363. total := 0
  364. for _, elem := range t.TupleElems {
  365. total += getTypeSize(*elem)
  366. }
  367. return total
  368. }
  369. return 32
  370. }
  371. // isLetter reports whether a given 'rune' is classified as a Letter.
  372. // This method is copied from reflect/type.go
  373. func isLetter(ch rune) bool {
  374. return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
  375. }
  376. // isValidFieldName checks if a string is a valid (struct) field name or not.
  377. //
  378. // According to the language spec, a field name should be an identifier.
  379. //
  380. // identifier = letter { letter | unicode_digit } .
  381. // letter = unicode_letter | "_" .
  382. // This method is copied from reflect/type.go
  383. func isValidFieldName(fieldName string) bool {
  384. for i, c := range fieldName {
  385. if i == 0 && !isLetter(c) {
  386. return false
  387. }
  388. if !(isLetter(c) || unicode.IsDigit(c)) {
  389. return false
  390. }
  391. }
  392. return len(fieldName) > 0
  393. }