From ad18014854eb225a590f183a2b3d7fd77909e1ae Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 1 Apr 2020 14:06:08 +0200 Subject: [PATCH] accounts/abi/bind: use store function to remove code duplication --- accounts/abi/bind/topics.go | 79 +++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/accounts/abi/bind/topics.go b/accounts/abi/bind/topics.go index 7ebf510ee1..39c8084b1e 100644 --- a/accounts/abi/bind/topics.go +++ b/accounts/abi/bind/topics.go @@ -111,31 +111,28 @@ var ( ) // parseTopics converts the indexed topic fields into actual log field values. -// -// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256 -// hashes as the topic value! func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) error { - // Sanity check that the fields and topics match up - if len(fields) != len(topics) { - return errors.New("topic/field count mismatch") - } - // Iterate over all the fields and reconstruct them from topics - for i, arg := range fields { - if !arg.Indexed { - return errors.New("non-indexed field in topic reconstruction") - } + store := func(arg abi.Argument, reconstr interface{}) { field := reflect.ValueOf(out).Elem().FieldByName(capitalise(arg.Name)) - reconstr, err := parseField(arg, topics[i]) - if err != nil { - return err - } field.Set(reflect.ValueOf(reconstr)) } - return nil + return parseTopicIntoFunc(fields, topics, store) } // parseTopicsIntoMap converts the indexed topic field-value pairs into map key-value pairs func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics []common.Hash) error { + store := func(arg abi.Argument, reconstr interface{}) { + out[arg.Name] = reconstr + } + return parseTopicIntoFunc(fields, topics, store) +} + +// parseTopicIntoFunc converts the indexed topic field-value pairs and stores them using the +// provided store function. +// +// Note, dynamic types cannot be reconstructed since they get mapped to Keccak256 +// hashes as the topic value! +func parseTopicIntoFunc(fields abi.Arguments, topics []common.Hash, store func(abi.Argument, interface{})) error { // Sanity check that the fields and topics match up if len(fields) != len(topics) { return errors.New("topic/field count mismatch") @@ -145,34 +142,30 @@ func parseTopicsIntoMap(out map[string]interface{}, fields abi.Arguments, topics if !arg.Indexed { return errors.New("non-indexed field in topic reconstruction") } - reconstr, err := parseField(arg, topics[i]) - if err != nil { - return err + //reconstr, err := parseField(arg, topics[i]) + var reconstr interface{} + switch arg.Type.T { + case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: + // Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash + // whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash + reconstr = topics[i] + case abi.FunctionTy: + if garbage := binary.BigEndian.Uint64(topics[i][0:8]); garbage != 0 { + return fmt.Errorf("bind: got improperly encoded function type, got %v", topics[i].Bytes()) + } + var tmp [24]byte + copy(tmp[:], topics[i][8:32]) + reconstr = tmp + default: + var err error + reconstr, err = abi.ToGoType(0, arg.Type, topics[i].Bytes()) + if err != nil { + return err + } } - out[arg.Name] = reconstr + // Use the store function to store the value + store(arg, reconstr) } return nil } - -func parseField(arg abi.Argument, topic common.Hash) (interface{}, error) { - if !arg.Indexed { - return nil, errors.New("non-indexed field in topic reconstruction") - } - - switch arg.Type.T { - case abi.StringTy, abi.BytesTy, abi.SliceTy, abi.ArrayTy: - // Array types (including strings and bytes) have their keccak256 hashes stored in the topic- not a hash - // whose bytes can be decoded to the actual value- so the best we can do is retrieve that hash - return topic, nil - case abi.FunctionTy: - if garbage := binary.BigEndian.Uint64(topic[0:8]); garbage != 0 { - return nil, fmt.Errorf("bind: got improperly encoded function type, got %v", topic.Bytes()) - } - var tmp [24]byte - copy(tmp[:], topic[8:32]) - return tmp, nil - default: - return abi.ToGoType(0, arg.Type, topic.Bytes()) - } -}