Skip to content

Commit

Permalink
accounts/abi/bind: use store function to remove code duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
MariusVanDerWijden committed Apr 2, 2020
1 parent 2684fbb commit ad18014
Showing 1 changed file with 36 additions and 43 deletions.
79 changes: 36 additions & 43 deletions accounts/abi/bind/topics.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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())
}
}

0 comments on commit ad18014

Please sign in to comment.