abi.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum 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. // go-ethereum 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 go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package abi
  17. import (
  18. "encoding/json"
  19. "fmt"
  20. "io"
  21. "strings"
  22. "github.com/ethereum/go-ethereum/crypto"
  23. )
  24. // Callable method given a `Name` and whether the method is a constant.
  25. // If the method is `Const` no transaction needs to be created for this
  26. // particular Method call. It can easily be simulated using a local VM.
  27. // For example a `Balance()` method only needs to retrieve something
  28. // from the storage and therefor requires no Tx to be send to the
  29. // network. A method such as `Transact` does require a Tx and thus will
  30. // be flagged `true`.
  31. // Input specifies the required input parameters for this gives method.
  32. type Method struct {
  33. Name string
  34. Const bool
  35. Input []Argument
  36. Return Type // not yet implemented
  37. }
  38. // Returns the methods string signature according to the ABI spec.
  39. //
  40. // Example
  41. //
  42. // function foo(uint32 a, int b) = "foo(uint32,int256)"
  43. //
  44. // Please note that "int" is substitute for its canonical representation "int256"
  45. func (m Method) String() (out string) {
  46. out += m.Name
  47. types := make([]string, len(m.Input))
  48. i := 0
  49. for _, input := range m.Input {
  50. types[i] = input.Type.String()
  51. i++
  52. }
  53. out += "(" + strings.Join(types, ",") + ")"
  54. return
  55. }
  56. func (m Method) Id() []byte {
  57. return crypto.Sha3([]byte(m.String()))[:4]
  58. }
  59. // Argument holds the name of the argument and the corresponding type.
  60. // Types are used when packing and testing arguments.
  61. type Argument struct {
  62. Name string
  63. Type Type
  64. }
  65. func (a *Argument) UnmarshalJSON(data []byte) error {
  66. var extarg struct {
  67. Name string
  68. Type string
  69. }
  70. err := json.Unmarshal(data, &extarg)
  71. if err != nil {
  72. return fmt.Errorf("argument json err: %v", err)
  73. }
  74. a.Type, err = NewType(extarg.Type)
  75. if err != nil {
  76. return err
  77. }
  78. a.Name = extarg.Name
  79. return nil
  80. }
  81. // The ABI holds information about a contract's context and available
  82. // invokable methods. It will allow you to type check function calls and
  83. // packs data accordingly.
  84. type ABI struct {
  85. Methods map[string]Method
  86. }
  87. // tests, tests whether the given input would result in a successful
  88. // call. Checks argument list count and matches input to `input`.
  89. func (abi ABI) pack(name string, args ...interface{}) ([]byte, error) {
  90. method := abi.Methods[name]
  91. var ret []byte
  92. for i, a := range args {
  93. input := method.Input[i]
  94. packed, err := input.Type.pack(a)
  95. if err != nil {
  96. return nil, fmt.Errorf("`%s` %v", name, err)
  97. }
  98. ret = append(ret, packed...)
  99. }
  100. return ret, nil
  101. }
  102. // Pack the given method name to conform the ABI. Method call's data
  103. // will consist of method_id, args0, arg1, ... argN. Method id consists
  104. // of 4 bytes and arguments are all 32 bytes.
  105. // Method ids are created from the first 4 bytes of the hash of the
  106. // methods string signature. (signature = baz(uint32,string32))
  107. func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
  108. method, exist := abi.Methods[name]
  109. if !exist {
  110. return nil, fmt.Errorf("method '%s' not found", name)
  111. }
  112. // start with argument count match
  113. if len(args) != len(method.Input) {
  114. return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(method.Input))
  115. }
  116. arguments, err := abi.pack(name, args...)
  117. if err != nil {
  118. return nil, err
  119. }
  120. // Set function id
  121. packed := abi.Methods[name].Id()
  122. packed = append(packed, arguments...)
  123. return packed, nil
  124. }
  125. func (abi *ABI) UnmarshalJSON(data []byte) error {
  126. var methods []Method
  127. if err := json.Unmarshal(data, &methods); err != nil {
  128. return err
  129. }
  130. abi.Methods = make(map[string]Method)
  131. for _, method := range methods {
  132. abi.Methods[method.Name] = method
  133. }
  134. return nil
  135. }
  136. func JSON(reader io.Reader) (ABI, error) {
  137. dec := json.NewDecoder(reader)
  138. var abi ABI
  139. if err := dec.Decode(&abi); err != nil {
  140. return ABI{}, err
  141. }
  142. return abi, nil
  143. }