accounts/abi, signer/fourbyte: fix incorrect signature

This commit is contained in:
rjl493456442 2019-07-24 15:05:23 +08:00
parent e46a01d56c
commit 29ac361e85
6 changed files with 79 additions and 25 deletions

View file

@ -121,11 +121,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
Inputs []Argument
Outputs []Argument
}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
abi.Methods = make(map[string]Method)
abi.Events = make(map[string]Event)
for _, field := range fields {
@ -144,6 +142,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Methods[name] = Method{
Name: name,
RawName: field.Name,
Const: field.Constant,
Inputs: field.Inputs,
Outputs: field.Outputs,
@ -157,6 +156,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
abi.Events[name] = Event{
Name: name,
RawName: field.Name,
Anonymous: field.Anonymous,
Inputs: field.Inputs,
}

View file

@ -61,10 +61,10 @@ func TestReader(t *testing.T) {
exp := ABI{
Methods: map[string]Method{
"balance": {
"balance", true, nil, nil,
"balance", "balance", true, nil, nil,
},
"send": {
"send", false, []Argument{
"send", "send", false, []Argument{
{"amount", Uint256, false},
}, nil,
},
@ -162,12 +162,10 @@ func TestTestSlice(t *testing.T) {
if err != nil {
t.Fatal(err)
}
slice := make([]uint64, 2)
if _, err := abi.Pack("uint64[2]", slice); err != nil {
t.Error(err)
}
if _, err := abi.Pack("uint64[]", slice); err != nil {
t.Error(err)
}
@ -175,7 +173,7 @@ func TestTestSlice(t *testing.T) {
func TestMethodSignature(t *testing.T) {
String, _ := NewType("string", nil)
m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
m := Method{"foo", "foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
exp := "foo(string,string)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
@ -187,7 +185,7 @@ func TestMethodSignature(t *testing.T) {
}
uintt, _ := NewType("uint256", nil)
m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
m = Method{"foo", "foo", false, []Argument{{"bar", uintt, false}}, nil}
exp = "foo(uint256)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
@ -206,13 +204,36 @@ func TestMethodSignature(t *testing.T) {
{Name: "y", Type: "int256"},
}},
})
m = Method{"foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
m = Method{"foo", "foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
}
}
func TestOverloadedMethodSignature(t *testing.T) {
json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
abi, err := JSON(strings.NewReader(json))
if err != nil {
t.Fatal(err)
}
check := func(name string, expect string, method bool) {
if method {
if abi.Methods[name].Sig() != expect {
t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig())
}
} else {
if abi.Events[name].Sig() != expect {
t.Fatalf("The signature of overloaded event mismatch, want %s, have %s", expect, abi.Events[name].Sig())
}
}
}
check("foo", "foo(uint256,uint256)", true)
check("foo0", "foo(uint256)", true)
check("bar", "bar(uint256)", false)
check("bar0", "bar(uint256,uint256)", false)
}
func TestMultiPack(t *testing.T) {
abi, err := JSON(strings.NewReader(jsondata2))
if err != nil {

View file

@ -541,7 +541,7 @@ func formatMethod(method abi.Method, structs map[string]*tmplStruct) string {
if method.Const {
constant = "constant "
}
return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
}
// formatEvent transforms raw event representation into a user friendly one.
@ -554,5 +554,5 @@ func formatEvent(event abi.Event, structs map[string]*tmplStruct) string {
inputs[i] = fmt.Sprintf("%v %v", resolveArgName(input, structs), input.Name)
}
}
return fmt.Sprintf("event %v(%v)", event.Name, strings.Join(inputs, ", "))
return fmt.Sprintf("event %v(%v)", event.RawName, strings.Join(inputs, ", "))
}

View file

@ -28,7 +28,19 @@ import (
// holds type information (inputs) about the yielded output. Anonymous events
// don't get the signature canonical representation as the first LOG topic.
type Event struct {
Name string
// Name the name of the event used for internal representation. which
// It's derived from raw name and will be added suffix when event
// overload occurs.
//
// e.g.
// There are two events have same name:
// * foo(int,int)
// * foo(uint,uint)
// The method name of the first one can be resolved as foo while the
// second one can be resolved as foo0.
Name string
// RawName raw method name parsed from ABI
RawName string
Anonymous bool
Inputs Arguments
}
@ -41,17 +53,26 @@ func (e Event) String() string {
inputs[i] = fmt.Sprintf("%v indexed %v", input.Type, input.Name)
}
}
return fmt.Sprintf("event %v(%v)", e.Name, strings.Join(inputs, ", "))
return fmt.Sprintf("event %v(%v)", e.RawName, strings.Join(inputs, ", "))
}
// Sig returns the methods string signature according to the ABI spec.
//
// Example
//
// event foo(uint32 a, int b) = "foo(uint32,int256)"
//
// Please note that "int" is substitute for its canonical representation "int256"
func (e Event) Sig() string {
types := make([]string, len(e.Inputs))
for i, input := range e.Inputs {
types[i] = input.Type.String()
}
return fmt.Sprintf("%v(%v)", e.RawName, strings.Join(types, ","))
}
// Id returns the canonical representation of the event's signature used by the
// abi definition to identify event names and types.
func (e Event) Id() common.Hash {
types := make([]string, len(e.Inputs))
i := 0
for _, input := range e.Inputs {
types[i] = input.Type.String()
i++
}
return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ",")))))
return common.BytesToHash(crypto.Keccak256([]byte(e.Sig())))
}

View file

@ -32,7 +32,19 @@ import (
// be flagged `false`.
// Input specifies the required input parameters for this gives method.
type Method struct {
Name string
// Name the name of the method used for internal representation. which
// It's derived from raw name and will be added suffix when function
// overload occurs.
//
// e.g.
// There are two functions have same name:
// * foo(int,int)
// * foo(uint,uint)
// The method name of the first one can be resolved as foo while the
// second one can be resolved as foo0.
Name string
// RawName raw method name parsed from ABI
RawName string
Const bool
Inputs Arguments
Outputs Arguments
@ -42,7 +54,7 @@ type Method struct {
//
// Example
//
// function foo(uint32 a, int b) = "foo(uint32,int256)"
// function foo(uint32 a, int b) = "foo(uint32,int256)"
//
// Please note that "int" is substitute for its canonical representation "int256"
func (method Method) Sig() string {
@ -50,7 +62,7 @@ func (method Method) Sig() string {
for i, input := range method.Inputs {
types[i] = input.Type.String()
}
return fmt.Sprintf("%v(%v)", method.Name, strings.Join(types, ","))
return fmt.Sprintf("%v(%v)", method.RawName, strings.Join(types, ","))
}
func (method Method) String() string {
@ -69,7 +81,7 @@ func (method Method) String() string {
if method.Const {
constant = "constant "
}
return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.Name, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
return fmt.Sprintf("function %v(%v) %sreturns(%v)", method.RawName, strings.Join(inputs, ", "), constant, strings.Join(outputs, ", "))
}
func (method Method) Id() []byte {

View file

@ -140,7 +140,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
return nil, err
}
// Everything valid, assemble the call infos for the signer
decoded := decodedCallData{signature: method.Sig(), name: method.Name}
decoded := decodedCallData{signature: method.Sig(), name: method.RawName}
for i := 0; i < len(method.Inputs); i++ {
decoded.inputs = append(decoded.inputs, decodedArgument{
soltype: method.Inputs[i],