argument.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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. "encoding/json"
  19. "fmt"
  20. "reflect"
  21. "strings"
  22. )
  23. // Argument holds the name of the argument and the corresponding type.
  24. // Types are used when packing and testing arguments.
  25. type Argument struct {
  26. Name string
  27. Type Type
  28. Indexed bool // indexed is only used by events
  29. }
  30. type Arguments []Argument
  31. type ArgumentMarshaling struct {
  32. Name string
  33. Type string
  34. InternalType string
  35. Components []ArgumentMarshaling
  36. Indexed bool
  37. }
  38. // UnmarshalJSON implements json.Unmarshaler interface
  39. func (argument *Argument) UnmarshalJSON(data []byte) error {
  40. var arg ArgumentMarshaling
  41. err := json.Unmarshal(data, &arg)
  42. if err != nil {
  43. return fmt.Errorf("argument json err: %v", err)
  44. }
  45. argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components)
  46. if err != nil {
  47. return err
  48. }
  49. argument.Name = arg.Name
  50. argument.Indexed = arg.Indexed
  51. return nil
  52. }
  53. // LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events
  54. // can ever have 'indexed' arguments, it should always be false on arguments for method input/output
  55. func (arguments Arguments) LengthNonIndexed() int {
  56. out := 0
  57. for _, arg := range arguments {
  58. if !arg.Indexed {
  59. out++
  60. }
  61. }
  62. return out
  63. }
  64. // NonIndexed returns the arguments with indexed arguments filtered out
  65. func (arguments Arguments) NonIndexed() Arguments {
  66. var ret []Argument
  67. for _, arg := range arguments {
  68. if !arg.Indexed {
  69. ret = append(ret, arg)
  70. }
  71. }
  72. return ret
  73. }
  74. // isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
  75. func (arguments Arguments) isTuple() bool {
  76. return len(arguments) > 1
  77. }
  78. // Unpack performs the operation hexdata -> Go format
  79. func (arguments Arguments) Unpack(v interface{}, data []byte) error {
  80. if len(data) == 0 {
  81. if len(arguments) != 0 {
  82. return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
  83. }
  84. return nil // Nothing to unmarshal, return
  85. }
  86. // make sure the passed value is arguments pointer
  87. if reflect.Ptr != reflect.ValueOf(v).Kind() {
  88. return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
  89. }
  90. marshalledValues, err := arguments.UnpackValues(data)
  91. if err != nil {
  92. return err
  93. }
  94. if len(marshalledValues) == 0 {
  95. return fmt.Errorf("abi: Unpack(no-values unmarshalled %T)", v)
  96. }
  97. if arguments.isTuple() {
  98. return arguments.unpackTuple(v, marshalledValues)
  99. }
  100. return arguments.unpackAtomic(v, marshalledValues[0])
  101. }
  102. // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value
  103. func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
  104. // Make sure map is not nil
  105. if v == nil {
  106. return fmt.Errorf("abi: cannot unpack into a nil map")
  107. }
  108. if len(data) == 0 {
  109. if len(arguments) != 0 {
  110. return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
  111. }
  112. return nil // Nothing to unmarshal, return
  113. }
  114. marshalledValues, err := arguments.UnpackValues(data)
  115. if err != nil {
  116. return err
  117. }
  118. for i, arg := range arguments.NonIndexed() {
  119. v[arg.Name] = marshalledValues[i]
  120. }
  121. return nil
  122. }
  123. // unpack sets the unmarshalled value to go format.
  124. // Note the dst here must be settable.
  125. func unpack(t *Type, dst interface{}, src interface{}) error {
  126. var (
  127. dstVal = reflect.ValueOf(dst).Elem()
  128. srcVal = reflect.ValueOf(src)
  129. )
  130. tuple, typ := false, t
  131. for {
  132. if typ.T == SliceTy || typ.T == ArrayTy {
  133. typ = typ.Elem
  134. continue
  135. }
  136. tuple = typ.T == TupleTy
  137. break
  138. }
  139. if !tuple {
  140. return set(dstVal, srcVal)
  141. }
  142. // Dereferences interface or pointer wrapper
  143. dstVal = indirectInterfaceOrPtr(dstVal)
  144. switch t.T {
  145. case TupleTy:
  146. if dstVal.Kind() != reflect.Struct {
  147. return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind())
  148. }
  149. fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal)
  150. if err != nil {
  151. return err
  152. }
  153. for i, elem := range t.TupleElems {
  154. fname := fieldmap[t.TupleRawNames[i]]
  155. field := dstVal.FieldByName(fname)
  156. if !field.IsValid() {
  157. return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i])
  158. }
  159. if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil {
  160. return err
  161. }
  162. }
  163. return nil
  164. case SliceTy:
  165. if dstVal.Kind() != reflect.Slice {
  166. return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind())
  167. }
  168. slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len())
  169. for i := 0; i < slice.Len(); i++ {
  170. if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
  171. return err
  172. }
  173. }
  174. dstVal.Set(slice)
  175. case ArrayTy:
  176. if dstVal.Kind() != reflect.Array {
  177. return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind())
  178. }
  179. array := reflect.New(dstVal.Type()).Elem()
  180. for i := 0; i < array.Len(); i++ {
  181. if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
  182. return err
  183. }
  184. }
  185. dstVal.Set(array)
  186. }
  187. return nil
  188. }
  189. // unpackAtomic unpacks ( hexdata -> go ) a single value
  190. func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
  191. if arguments.LengthNonIndexed() == 0 {
  192. return nil
  193. }
  194. argument := arguments.NonIndexed()[0]
  195. elem := reflect.ValueOf(v).Elem()
  196. if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
  197. fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
  198. if err != nil {
  199. return err
  200. }
  201. field := elem.FieldByName(fieldmap[argument.Name])
  202. if !field.IsValid() {
  203. return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name)
  204. }
  205. return unpack(&argument.Type, field.Addr().Interface(), marshalledValues)
  206. }
  207. return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
  208. }
  209. // unpackTuple unpacks ( hexdata -> go ) a batch of values.
  210. func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
  211. var (
  212. value = reflect.ValueOf(v).Elem()
  213. typ = value.Type()
  214. kind = value.Kind()
  215. nonIndexedArgs = arguments.NonIndexed()
  216. )
  217. if err := requireUnpackKind(value, len(nonIndexedArgs), arguments); err != nil {
  218. return err
  219. }
  220. // If the interface is a struct, get of abi->struct_field mapping
  221. var abi2struct map[string]string
  222. if kind == reflect.Struct {
  223. argNames := make([]string, len(nonIndexedArgs))
  224. for i, arg := range nonIndexedArgs {
  225. argNames[i] = arg.Name
  226. }
  227. var err error
  228. if abi2struct, err = mapArgNamesToStructFields(argNames, value); err != nil {
  229. return err
  230. }
  231. }
  232. for i, arg := range nonIndexedArgs {
  233. switch kind {
  234. case reflect.Struct:
  235. field := value.FieldByName(abi2struct[arg.Name])
  236. if !field.IsValid() {
  237. return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name)
  238. }
  239. if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil {
  240. return err
  241. }
  242. case reflect.Slice, reflect.Array:
  243. if value.Len() < i {
  244. return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
  245. }
  246. v := value.Index(i)
  247. if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
  248. return err
  249. }
  250. if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
  251. return err
  252. }
  253. default:
  254. return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
  255. }
  256. }
  257. return nil
  258. }
  259. // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
  260. // without supplying a struct to unpack into. Instead, this method returns a list containing the
  261. // values. An atomic argument will be a list with one element.
  262. func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
  263. retval := make([]interface{}, 0, arguments.LengthNonIndexed())
  264. virtualArgs := 0
  265. for index, arg := range arguments.NonIndexed() {
  266. marshalledValue, err := ToGoType((index+virtualArgs)*32, arg.Type, data)
  267. if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
  268. // If we have a static array, like [3]uint256, these are coded as
  269. // just like uint256,uint256,uint256.
  270. // This means that we need to add two 'virtual' arguments when
  271. // we count the index from now on.
  272. //
  273. // Array values nested multiple levels deep are also encoded inline:
  274. // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256
  275. //
  276. // Calculate the full array size to get the correct offset for the next argument.
  277. // Decrement it by 1, as the normal index increment is still applied.
  278. virtualArgs += getTypeSize(arg.Type)/32 - 1
  279. } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) {
  280. // If we have a static tuple, like (uint256, bool, uint256), these are
  281. // coded as just like uint256,bool,uint256
  282. virtualArgs += getTypeSize(arg.Type)/32 - 1
  283. }
  284. if err != nil {
  285. return nil, err
  286. }
  287. retval = append(retval, marshalledValue)
  288. }
  289. return retval, nil
  290. }
  291. // PackValues performs the operation Go format -> Hexdata
  292. // It is the semantic opposite of UnpackValues
  293. func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
  294. return arguments.Pack(args...)
  295. }
  296. // Pack performs the operation Go format -> Hexdata
  297. func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
  298. // Make sure arguments match up and pack them
  299. abiArgs := arguments
  300. if len(args) != len(abiArgs) {
  301. return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
  302. }
  303. // variable input is the output appended at the end of packed
  304. // output. This is used for strings and bytes types input.
  305. var variableInput []byte
  306. // input offset is the bytes offset for packed output
  307. inputOffset := 0
  308. for _, abiArg := range abiArgs {
  309. inputOffset += getTypeSize(abiArg.Type)
  310. }
  311. var ret []byte
  312. for i, a := range args {
  313. input := abiArgs[i]
  314. // pack the input
  315. packed, err := input.Type.pack(reflect.ValueOf(a))
  316. if err != nil {
  317. return nil, err
  318. }
  319. // check for dynamic types
  320. if isDynamicType(input.Type) {
  321. // set the offset
  322. ret = append(ret, packNum(reflect.ValueOf(inputOffset))...)
  323. // calculate next offset
  324. inputOffset += len(packed)
  325. // append to variable input
  326. variableInput = append(variableInput, packed...)
  327. } else {
  328. // append the packed value to the input
  329. ret = append(ret, packed...)
  330. }
  331. }
  332. // append the variable input at the end of the packed input
  333. ret = append(ret, variableInput...)
  334. return ret, nil
  335. }
  336. // ToCamelCase converts an under-score string to a camel-case string
  337. func ToCamelCase(input string) string {
  338. parts := strings.Split(input, "_")
  339. for i, s := range parts {
  340. if len(s) > 0 {
  341. parts[i] = strings.ToUpper(s[:1]) + s[1:]
  342. }
  343. }
  344. return strings.Join(parts, "")
  345. }