mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/abi: prevent recalculation of internal
In this commit, I changed the way we calculate the string representations, sig representations and the id's of methods. Before that these fields would be recalculated everytime someone called .Sig() .String() or .ID() on a method or an event. Additionally this commit fixes issue #20856 as we assign names to inputs with no name (input with name "" becomes "arg0")
This commit is contained in:
parent
07f5bc448e
commit
b98e4dcce4
10 changed files with 123 additions and 158 deletions
|
|
@ -76,7 +76,7 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
// Pack up the method ID too if not a constructor and return
|
||||
return append(method.ID(), arguments...), nil
|
||||
return append(method.ID, arguments...), nil
|
||||
}
|
||||
|
||||
// Unpack output in v according to the abi specification
|
||||
|
|
@ -163,13 +163,8 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
abi.Receive = NewMethod("", "", "payable", field.Constant, field.Payable, false, true, nil, nil)
|
||||
case "event":
|
||||
abi.Events[name] = Event{
|
||||
Name: name,
|
||||
RawName: field.Name,
|
||||
Anonymous: field.Anonymous,
|
||||
Inputs: field.Inputs,
|
||||
}
|
||||
name := abi.eventName(field.Name)
|
||||
abi.Events[name] = NewEvent(name, field.Name, field.Anonymous, field.Inputs)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -210,7 +205,7 @@ func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
|
|||
return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata))
|
||||
}
|
||||
for _, method := range abi.Methods {
|
||||
if bytes.Equal(method.ID(), sigdata[:4]) {
|
||||
if bytes.Equal(method.ID, sigdata[:4]) {
|
||||
return &method, nil
|
||||
}
|
||||
}
|
||||
|
|
@ -221,7 +216,7 @@ func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
|
|||
// ABI and returns nil if none found.
|
||||
func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
|
||||
for _, event := range abi.Events {
|
||||
if bytes.Equal(event.ID().Bytes(), topic.Bytes()) {
|
||||
if bytes.Equal(event.ID.Bytes(), topic.Bytes()) {
|
||||
return &event, nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,20 +169,20 @@ func TestMethodSignature(t *testing.T) {
|
|||
String, _ := NewType("string", "", nil)
|
||||
m := NewMethod("foo", "foo", "", false, false, false, false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil)
|
||||
exp := "foo(string,string)"
|
||||
if m.Sig() != exp {
|
||||
t.Error("signature mismatch", exp, "!=", m.Sig())
|
||||
if m.Sig != exp {
|
||||
t.Error("signature mismatch", exp, "!=", m.Sig)
|
||||
}
|
||||
|
||||
idexp := crypto.Keccak256([]byte(exp))[:4]
|
||||
if !bytes.Equal(m.ID(), idexp) {
|
||||
t.Errorf("expected ids to match %x != %x", m.ID(), idexp)
|
||||
if !bytes.Equal(m.ID, idexp) {
|
||||
t.Errorf("expected ids to match %x != %x", m.ID, idexp)
|
||||
}
|
||||
|
||||
uintt, _ := NewType("uint256", "", nil)
|
||||
m = NewMethod("foo", "foo", "", false, false, false, false, []Argument{{"bar", uintt, false}}, nil)
|
||||
exp = "foo(uint256)"
|
||||
if m.Sig() != exp {
|
||||
t.Error("signature mismatch", exp, "!=", m.Sig())
|
||||
if m.Sig != exp {
|
||||
t.Error("signature mismatch", exp, "!=", m.Sig)
|
||||
}
|
||||
|
||||
// Method with tuple arguments
|
||||
|
|
@ -200,8 +200,8 @@ func TestMethodSignature(t *testing.T) {
|
|||
})
|
||||
m = NewMethod("foo", "foo", "", false, false, false, 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())
|
||||
if m.Sig != exp {
|
||||
t.Error("signature mismatch", exp, "!=", m.Sig)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,12 +213,12 @@ func TestOverloadedMethodSignature(t *testing.T) {
|
|||
}
|
||||
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())
|
||||
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())
|
||||
if abi.Events[name].Sig != expect {
|
||||
t.Fatalf("The signature of overloaded event mismatch, want %s, have %s", expect, abi.Events[name].Sig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -915,13 +915,13 @@ func TestABI_MethodById(t *testing.T) {
|
|||
}
|
||||
for name, m := range abi.Methods {
|
||||
a := fmt.Sprintf("%v", m)
|
||||
m2, err := abi.MethodById(m.ID())
|
||||
m2, err := abi.MethodById(m.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to look up ABI method: %v", err)
|
||||
}
|
||||
b := fmt.Sprintf("%v", m2)
|
||||
if a != b {
|
||||
t.Errorf("Method %v (id %x) not 'findable' by id in ABI", name, m.ID())
|
||||
t.Errorf("Method %v (id %x) not 'findable' by id in ABI", name, m.ID)
|
||||
}
|
||||
}
|
||||
// Also test empty
|
||||
|
|
@ -989,8 +989,8 @@ func TestABI_EventById(t *testing.T) {
|
|||
t.Errorf("We should find a event for topic %s, test #%d", topicID.Hex(), testnum)
|
||||
}
|
||||
|
||||
if event.ID() != topicID {
|
||||
t.Errorf("Event id %s does not match topic %s, test #%d", event.ID().Hex(), topicID.Hex(), testnum)
|
||||
if event.ID != topicID {
|
||||
t.Errorf("Event id %s does not match topic %s, test #%d", event.ID.Hex(), topicID.Hex(), testnum)
|
||||
}
|
||||
|
||||
unknowntopicID := crypto.Keccak256Hash([]byte("unknownEvent"))
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ func (c *BoundContract) FilterLogs(opts *FilterOpts, name string, query ...[]int
|
|||
opts = new(FilterOpts)
|
||||
}
|
||||
// Append the event selector to the query parameters and construct the topic set
|
||||
query = append([][]interface{}{{c.abi.Events[name].ID()}}, query...)
|
||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
||||
|
||||
topics, err := makeTopics(query...)
|
||||
if err != nil {
|
||||
|
|
@ -313,7 +313,7 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]inter
|
|||
opts = new(WatchOpts)
|
||||
}
|
||||
// Append the event selector to the query parameters and construct the topic set
|
||||
query = append([][]interface{}{{c.abi.Events[name].ID()}}, query...)
|
||||
query = append([][]interface{}{{c.abi.Events[name].ID}}, query...)
|
||||
|
||||
topics, err := makeTopics(query...)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -42,36 +42,59 @@ type Event struct {
|
|||
RawName string
|
||||
Anonymous bool
|
||||
Inputs Arguments
|
||||
str string
|
||||
// Sig contains the string signature according to the ABI spec.
|
||||
// e.g. event foo(uint32 a, int b) = "foo(uint32,int256)"
|
||||
// Please note that "int" is substitute for its canonical representation "int256"
|
||||
Sig string
|
||||
// ID returns the canonical representation of the event's signature used by the
|
||||
// abi definition to identify event names and types.
|
||||
ID common.Hash
|
||||
}
|
||||
|
||||
// NewEvent creates a new Event.
|
||||
// It sanitizes the input arguments to remove unnamed arguments.
|
||||
// It also precomputes the id, signature and string representation
|
||||
// of the event.
|
||||
func NewEvent(name, rawName string, anonymous bool, inputs Arguments) Event {
|
||||
// sanitize inputs to remove inputs without names
|
||||
// and precompute string and sig representation.
|
||||
names := make([]string, len(inputs))
|
||||
types := make([]string, len(inputs))
|
||||
for i, input := range inputs {
|
||||
if input.Name == "" {
|
||||
inputs[i] = Argument{
|
||||
Name: fmt.Sprintf("arg%d", i),
|
||||
Indexed: input.Indexed,
|
||||
Type: input.Type,
|
||||
}
|
||||
} else {
|
||||
inputs[i] = input
|
||||
}
|
||||
// string representation
|
||||
names[i] = fmt.Sprintf("%v %v", input.Type, inputs[i].Name)
|
||||
if input.Indexed {
|
||||
names[i] = fmt.Sprintf("%v indexed %v", input.Type, inputs[i].Name)
|
||||
}
|
||||
// sig representation
|
||||
types[i] = input.Type.String()
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("event %v(%v)", rawName, strings.Join(names, ", "))
|
||||
sig := fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
|
||||
id := common.BytesToHash(crypto.Keccak256([]byte(sig)))
|
||||
|
||||
return Event{
|
||||
Name: name,
|
||||
RawName: rawName,
|
||||
Anonymous: anonymous,
|
||||
Inputs: inputs,
|
||||
str: str,
|
||||
Sig: sig,
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (e Event) String() string {
|
||||
inputs := make([]string, len(e.Inputs))
|
||||
for i, input := range e.Inputs {
|
||||
inputs[i] = fmt.Sprintf("%v %v", input.Type, input.Name)
|
||||
if input.Indexed {
|
||||
inputs[i] = fmt.Sprintf("%v indexed %v", input.Type, input.Name)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("event %v(%v)", e.RawName, strings.Join(inputs, ", "))
|
||||
}
|
||||
|
||||
// Sig returns the event 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 {
|
||||
return common.BytesToHash(crypto.Keccak256([]byte(e.Sig())))
|
||||
return e.str
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ func TestEventId(t *testing.T) {
|
|||
}
|
||||
|
||||
for name, event := range abi.Events {
|
||||
if event.ID() != test.expectations[name] {
|
||||
t.Errorf("expected id to be %x, got %x", test.expectations[name], event.ID())
|
||||
if event.ID != test.expectations[name] {
|
||||
t.Errorf("expected id to be %x, got %x", test.expectations[name], event.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,10 +60,14 @@ type Method struct {
|
|||
|
||||
Inputs Arguments
|
||||
Outputs Arguments
|
||||
// internal fields to prevent recalculation
|
||||
sig string
|
||||
id []byte
|
||||
str string
|
||||
str string
|
||||
// Sig returns the methods string signature according to the ABI spec.
|
||||
// e.g. function foo(uint32 a, int b) = "foo(uint32,int256)"
|
||||
// Please note that "int" is substitute for its canonical representation "int256"
|
||||
Sig string
|
||||
// ID returns the canonical representation of the method's signature used by the
|
||||
// abi definition to identify method names and types.
|
||||
ID []byte
|
||||
}
|
||||
|
||||
// NewMethod creates a new Method.
|
||||
|
|
@ -71,6 +75,30 @@ type Method struct {
|
|||
// of the method.
|
||||
// A method should always be created using NewMethod.
|
||||
func NewMethod(name string, rawName string, mutability string, isConst, isPayable, isFallback, isReceive bool, inputs Arguments, outputs Arguments) Method {
|
||||
// inputs
|
||||
inputNames := make([]string, len(inputs))
|
||||
types := make([]string, len(inputs))
|
||||
for i, input := range inputs {
|
||||
inputNames[i] = fmt.Sprintf("%v %v", input.Type, input.Name)
|
||||
types[i] = input.Type.String()
|
||||
}
|
||||
// outputs
|
||||
outputNames := make([]string, len(outputs))
|
||||
for i, output := range outputs {
|
||||
outputNames[i] = output.Type.String()
|
||||
if len(output.Name) > 0 {
|
||||
outputNames[i] += fmt.Sprintf(" %v", output.Name)
|
||||
}
|
||||
}
|
||||
constant := ""
|
||||
if isConst {
|
||||
constant = "constant "
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("function %v(%v) %sreturns(%v)", rawName, strings.Join(inputNames, ", "), constant, strings.Join(outputNames, ", "))
|
||||
sig := fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ","))
|
||||
id := crypto.Keccak256([]byte(sig))[:4]
|
||||
|
||||
method := Method{
|
||||
Name: name,
|
||||
RawName: rawName,
|
||||
|
|
@ -81,94 +109,13 @@ func NewMethod(name string, rawName string, mutability string, isConst, isPayabl
|
|||
IsReceive: isReceive,
|
||||
Inputs: inputs,
|
||||
Outputs: outputs,
|
||||
str: str,
|
||||
Sig: sig,
|
||||
ID: id,
|
||||
}
|
||||
method.initFields()
|
||||
return method
|
||||
}
|
||||
|
||||
// initFields should only be used in the unit tests
|
||||
// to create valid Method objects from json.
|
||||
func (method *Method) initFields() {
|
||||
// Calculate and set Signature
|
||||
method.sig = method.calcSig()
|
||||
// Calculate the method id as the first 4 bytes of the hash of sig.
|
||||
method.id = crypto.Keccak256([]byte(method.sig))[:4]
|
||||
// Calculate and set the String representation
|
||||
method.str = method.calcString()
|
||||
}
|
||||
|
||||
// Sig returns the methods string signature according to the ABI spec.
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// 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 {
|
||||
// Short circuit if the method is special. Fallback
|
||||
// and Receive don't have signature at all.
|
||||
if method.IsFallback || method.IsReceive {
|
||||
return ""
|
||||
}
|
||||
return method.sig
|
||||
}
|
||||
|
||||
func (method Method) String() string {
|
||||
return method.str
|
||||
}
|
||||
|
||||
// ID returns the canonical representation of the method's signature used by the
|
||||
// abi definition to identify method names and types.
|
||||
func (method Method) ID() []byte {
|
||||
return method.id
|
||||
}
|
||||
|
||||
// calcSig calculates the method string signature.
|
||||
func (method Method) calcSig() string {
|
||||
types := make([]string, len(method.Inputs))
|
||||
for i, input := range method.Inputs {
|
||||
types[i] = input.Type.String()
|
||||
}
|
||||
return fmt.Sprintf("%v(%v)", method.RawName, strings.Join(types, ","))
|
||||
}
|
||||
|
||||
func (method Method) calcString() string {
|
||||
inputs := make([]string, len(method.Inputs))
|
||||
for i, input := range method.Inputs {
|
||||
inputs[i] = fmt.Sprintf("%v %v", input.Type, input.Name)
|
||||
}
|
||||
outputs := make([]string, len(method.Outputs))
|
||||
for i, output := range method.Outputs {
|
||||
outputs[i] = output.Type.String()
|
||||
if len(output.Name) > 0 {
|
||||
outputs[i] += fmt.Sprintf(" %v", output.Name)
|
||||
}
|
||||
}
|
||||
// Extract meaningful state mutability of solidity method.
|
||||
// If it's default value, never print it.
|
||||
state := method.StateMutability
|
||||
if state == "nonpayable" {
|
||||
state = ""
|
||||
}
|
||||
if state != "" {
|
||||
state = state + " "
|
||||
}
|
||||
identity := fmt.Sprintf("function %v", method.RawName)
|
||||
if method.IsFallback {
|
||||
identity = "fallback"
|
||||
} else if method.IsReceive {
|
||||
identity = "receive"
|
||||
}
|
||||
return fmt.Sprintf("%v(%v) %sreturns(%v)", identity, strings.Join(inputs, ", "), state, strings.Join(outputs, ", "))
|
||||
}
|
||||
|
||||
// IsConstant returns the indicator whether the method is read-only.
|
||||
func (method Method) IsConstant() bool {
|
||||
return method.StateMutability == "view" || method.StateMutability == "pure" || method.Constant
|
||||
}
|
||||
|
||||
// IsPayable returns the indicator whether the method can process
|
||||
// plain ether transfers.
|
||||
func (method Method) IsPayable() bool {
|
||||
return method.StateMutability == "payable" || method.Payable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ func TestMethodSig(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, test := range cases {
|
||||
got := abi.Methods[test.method].Sig()
|
||||
got := abi.Methods[test.method].Sig
|
||||
if got != test.expect {
|
||||
t.Errorf("expected string to be %s, got %s", test.expect, got)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ func TestMethodPack(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig := abi.Methods["slice"].ID()
|
||||
sig := abi.Methods["slice"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
|
||||
|
||||
|
|
@ -648,7 +648,7 @@ func TestMethodPack(t *testing.T) {
|
|||
}
|
||||
|
||||
var addrA, addrB = common.Address{1}, common.Address{2}
|
||||
sig = abi.Methods["sliceAddress"].ID()
|
||||
sig = abi.Methods["sliceAddress"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{32}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes(addrA[:], 32)...)
|
||||
|
|
@ -663,7 +663,7 @@ func TestMethodPack(t *testing.T) {
|
|||
}
|
||||
|
||||
var addrC, addrD = common.Address{3}, common.Address{4}
|
||||
sig = abi.Methods["sliceMultiAddress"].ID()
|
||||
sig = abi.Methods["sliceMultiAddress"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{64}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{160}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
|
||||
|
|
@ -681,7 +681,7 @@ func TestMethodPack(t *testing.T) {
|
|||
t.Errorf("expected %x got %x", sig, packed)
|
||||
}
|
||||
|
||||
sig = abi.Methods["slice256"].ID()
|
||||
sig = abi.Methods["slice256"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
|
||||
|
||||
|
|
@ -695,7 +695,7 @@ func TestMethodPack(t *testing.T) {
|
|||
}
|
||||
|
||||
a := [2][2]*big.Int{{big.NewInt(1), big.NewInt(1)}, {big.NewInt(2), big.NewInt(0)}}
|
||||
sig = abi.Methods["nestedArray"].ID()
|
||||
sig = abi.Methods["nestedArray"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{1}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{2}, 32)...)
|
||||
|
|
@ -712,7 +712,7 @@ func TestMethodPack(t *testing.T) {
|
|||
t.Errorf("expected %x got %x", sig, packed)
|
||||
}
|
||||
|
||||
sig = abi.Methods["nestedArray2"].ID()
|
||||
sig = abi.Methods["nestedArray2"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x80}, 32)...)
|
||||
|
|
@ -728,7 +728,7 @@ func TestMethodPack(t *testing.T) {
|
|||
t.Errorf("expected %x got %x", sig, packed)
|
||||
}
|
||||
|
||||
sig = abi.Methods["nestedSlice"].ID()
|
||||
sig = abi.Methods["nestedSlice"].ID
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x20}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x02}, 32)...)
|
||||
sig = append(sig, common.LeftPadBytes([]byte{0x40}, 32)...)
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
|
|||
return nil, fmt.Errorf("signature %q matches, but arguments mismatch: %v", method.String(), err)
|
||||
}
|
||||
// Everything valid, assemble the call infos for the signer
|
||||
decoded := decodedCallData{signature: method.Sig(), name: method.RawName}
|
||||
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],
|
||||
|
|
@ -158,7 +158,7 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
|
|||
if !bytes.Equal(encoded, argdata) {
|
||||
was := common.Bytes2Hex(encoded)
|
||||
exp := common.Bytes2Hex(argdata)
|
||||
return nil, fmt.Errorf("WARNING: Supplied data is stuffed with extra data. \nWant %s\nHave %s\nfor method %v", exp, was, method.Sig())
|
||||
return nil, fmt.Errorf("WARNING: Supplied data is stuffed with extra data. \nWant %s\nHave %s\nfor method %v", exp, was, method.Sig)
|
||||
}
|
||||
return &decoded, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ func TestEmbeddedDatabase(t *testing.T) {
|
|||
t.Errorf("Failed to get method by id (%s): %v", id, err)
|
||||
continue
|
||||
}
|
||||
if m.Sig() != selector {
|
||||
t.Errorf("Selector mismatch: have %v, want %v", m.Sig(), selector)
|
||||
if m.Sig != selector {
|
||||
t.Errorf("Selector mismatch: have %v, want %v", m.Sig, selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue