mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/abi, signer/fourbyte: fix incorrect signature
This commit is contained in:
parent
e46a01d56c
commit
29ac361e85
6 changed files with 79 additions and 25 deletions
|
|
@ -121,11 +121,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
|
||||||
Inputs []Argument
|
Inputs []Argument
|
||||||
Outputs []Argument
|
Outputs []Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &fields); err != nil {
|
if err := json.Unmarshal(data, &fields); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
abi.Methods = make(map[string]Method)
|
abi.Methods = make(map[string]Method)
|
||||||
abi.Events = make(map[string]Event)
|
abi.Events = make(map[string]Event)
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
|
|
@ -144,6 +142,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
abi.Methods[name] = Method{
|
abi.Methods[name] = Method{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
RawName: field.Name,
|
||||||
Const: field.Constant,
|
Const: field.Constant,
|
||||||
Inputs: field.Inputs,
|
Inputs: field.Inputs,
|
||||||
Outputs: field.Outputs,
|
Outputs: field.Outputs,
|
||||||
|
|
@ -157,6 +156,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
abi.Events[name] = Event{
|
abi.Events[name] = Event{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
RawName: field.Name,
|
||||||
Anonymous: field.Anonymous,
|
Anonymous: field.Anonymous,
|
||||||
Inputs: field.Inputs,
|
Inputs: field.Inputs,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,10 @@ func TestReader(t *testing.T) {
|
||||||
exp := ABI{
|
exp := ABI{
|
||||||
Methods: map[string]Method{
|
Methods: map[string]Method{
|
||||||
"balance": {
|
"balance": {
|
||||||
"balance", true, nil, nil,
|
"balance", "balance", true, nil, nil,
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"send", false, []Argument{
|
"send", "send", false, []Argument{
|
||||||
{"amount", Uint256, false},
|
{"amount", Uint256, false},
|
||||||
}, nil,
|
}, nil,
|
||||||
},
|
},
|
||||||
|
|
@ -162,12 +162,10 @@ func TestTestSlice(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
slice := make([]uint64, 2)
|
slice := make([]uint64, 2)
|
||||||
if _, err := abi.Pack("uint64[2]", slice); err != nil {
|
if _, err := abi.Pack("uint64[2]", slice); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := abi.Pack("uint64[]", slice); err != nil {
|
if _, err := abi.Pack("uint64[]", slice); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +173,7 @@ func TestTestSlice(t *testing.T) {
|
||||||
|
|
||||||
func TestMethodSignature(t *testing.T) {
|
func TestMethodSignature(t *testing.T) {
|
||||||
String, _ := NewType("string", nil)
|
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)"
|
exp := "foo(string,string)"
|
||||||
if m.Sig() != exp {
|
if m.Sig() != exp {
|
||||||
t.Error("signature mismatch", exp, "!=", m.Sig())
|
t.Error("signature mismatch", exp, "!=", m.Sig())
|
||||||
|
|
@ -187,7 +185,7 @@ func TestMethodSignature(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uintt, _ := NewType("uint256", nil)
|
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)"
|
exp = "foo(uint256)"
|
||||||
if m.Sig() != exp {
|
if m.Sig() != exp {
|
||||||
t.Error("signature mismatch", exp, "!=", m.Sig())
|
t.Error("signature mismatch", exp, "!=", m.Sig())
|
||||||
|
|
@ -206,13 +204,36 @@ func TestMethodSignature(t *testing.T) {
|
||||||
{Name: "y", Type: "int256"},
|
{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)"
|
exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)"
|
||||||
if m.Sig() != exp {
|
if m.Sig() != exp {
|
||||||
t.Error("signature mismatch", exp, "!=", m.Sig())
|
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) {
|
func TestMultiPack(t *testing.T) {
|
||||||
abi, err := JSON(strings.NewReader(jsondata2))
|
abi, err := JSON(strings.NewReader(jsondata2))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -541,7 +541,7 @@ func formatMethod(method abi.Method, structs map[string]*tmplStruct) string {
|
||||||
if method.Const {
|
if method.Const {
|
||||||
constant = "constant "
|
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.
|
// 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)
|
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, ", "))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,19 @@ import (
|
||||||
// holds type information (inputs) about the yielded output. Anonymous events
|
// holds type information (inputs) about the yielded output. Anonymous events
|
||||||
// don't get the signature canonical representation as the first LOG topic.
|
// don't get the signature canonical representation as the first LOG topic.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
|
// 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
|
Name string
|
||||||
|
// RawName raw method name parsed from ABI
|
||||||
|
RawName string
|
||||||
Anonymous bool
|
Anonymous bool
|
||||||
Inputs Arguments
|
Inputs Arguments
|
||||||
}
|
}
|
||||||
|
|
@ -41,17 +53,26 @@ func (e Event) String() string {
|
||||||
inputs[i] = fmt.Sprintf("%v indexed %v", input.Type, input.Name)
|
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
|
// Id returns the canonical representation of the event's signature used by the
|
||||||
// abi definition to identify event names and types.
|
// abi definition to identify event names and types.
|
||||||
func (e Event) Id() common.Hash {
|
func (e Event) Id() common.Hash {
|
||||||
types := make([]string, len(e.Inputs))
|
return common.BytesToHash(crypto.Keccak256([]byte(e.Sig())))
|
||||||
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, ",")))))
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,19 @@ import (
|
||||||
// be flagged `false`.
|
// be flagged `false`.
|
||||||
// Input specifies the required input parameters for this gives method.
|
// Input specifies the required input parameters for this gives method.
|
||||||
type Method struct {
|
type Method struct {
|
||||||
|
// 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
|
Name string
|
||||||
|
// RawName raw method name parsed from ABI
|
||||||
|
RawName string
|
||||||
Const bool
|
Const bool
|
||||||
Inputs Arguments
|
Inputs Arguments
|
||||||
Outputs Arguments
|
Outputs Arguments
|
||||||
|
|
@ -50,7 +62,7 @@ func (method Method) Sig() string {
|
||||||
for i, input := range method.Inputs {
|
for i, input := range method.Inputs {
|
||||||
types[i] = input.Type.String()
|
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 {
|
func (method Method) String() string {
|
||||||
|
|
@ -69,7 +81,7 @@ func (method Method) String() string {
|
||||||
if method.Const {
|
if method.Const {
|
||||||
constant = "constant "
|
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 {
|
func (method Method) Id() []byte {
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Everything valid, assemble the call infos for the signer
|
// 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++ {
|
for i := 0; i < len(method.Inputs); i++ {
|
||||||
decoded.inputs = append(decoded.inputs, decodedArgument{
|
decoded.inputs = append(decoded.inputs, decodedArgument{
|
||||||
soltype: method.Inputs[i],
|
soltype: method.Inputs[i],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue