github.com/tuotoo/go-ethereum@v1.7.4-0.20171121184211-049797d40a24/accounts/abi/event.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package abi
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  )
    27  
    28  // Event is an event potentially triggered by the EVM's LOG mechanism. The Event
    29  // holds type information (inputs) about the yielded output. Anonymous events
    30  // don't get the signature canonical representation as the first LOG topic.
    31  type Event struct {
    32  	Name      string
    33  	Anonymous bool
    34  	Inputs    []Argument
    35  }
    36  
    37  // Id returns the canonical representation of the event's signature used by the
    38  // abi definition to identify event names and types.
    39  func (e Event) Id() common.Hash {
    40  	types := make([]string, len(e.Inputs))
    41  	i := 0
    42  	for _, input := range e.Inputs {
    43  		types[i] = input.Type.String()
    44  		i++
    45  	}
    46  	return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ",")))))
    47  }
    48  
    49  // unpacks an event return tuple into a struct of corresponding go types
    50  //
    51  // Unpacking can be done into a struct or a slice/array.
    52  func (e Event) tupleUnpack(v interface{}, output []byte) error {
    53  	// make sure the passed value is a pointer
    54  	valueOf := reflect.ValueOf(v)
    55  	if reflect.Ptr != valueOf.Kind() {
    56  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
    57  	}
    58  
    59  	var (
    60  		value = valueOf.Elem()
    61  		typ   = value.Type()
    62  	)
    63  
    64  	if value.Kind() != reflect.Struct {
    65  		return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
    66  	}
    67  
    68  	j := 0
    69  	for i := 0; i < len(e.Inputs); i++ {
    70  		input := e.Inputs[i]
    71  		if input.Indexed {
    72  			// can't read, continue
    73  			continue
    74  		} else if input.Type.T == ArrayTy {
    75  			// need to move this up because they read sequentially
    76  			j += input.Type.Size
    77  		}
    78  		marshalledValue, err := toGoType((i+j)*32, input.Type, output)
    79  		if err != nil {
    80  			return err
    81  		}
    82  		reflectValue := reflect.ValueOf(marshalledValue)
    83  
    84  		switch value.Kind() {
    85  		case reflect.Struct:
    86  			for j := 0; j < typ.NumField(); j++ {
    87  				field := typ.Field(j)
    88  				// TODO read tags: `abi:"fieldName"`
    89  				if field.Name == strings.ToUpper(e.Inputs[i].Name[:1])+e.Inputs[i].Name[1:] {
    90  					if err := set(value.Field(j), reflectValue, e.Inputs[i]); err != nil {
    91  						return err
    92  					}
    93  				}
    94  			}
    95  		case reflect.Slice, reflect.Array:
    96  			if value.Len() < i {
    97  				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(e.Inputs), value.Len())
    98  			}
    99  			v := value.Index(i)
   100  			if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface {
   101  				return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type())
   102  			}
   103  			reflectValue := reflect.ValueOf(marshalledValue)
   104  			if err := set(v.Elem(), reflectValue, e.Inputs[i]); err != nil {
   105  				return err
   106  			}
   107  		default:
   108  			return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
   109  		}
   110  	}
   111  	return nil
   112  }
   113  
   114  func (e Event) isTupleReturn() bool { return len(e.Inputs) > 1 }
   115  
   116  func (e Event) singleUnpack(v interface{}, output []byte) error {
   117  	// make sure the passed value is a pointer
   118  	valueOf := reflect.ValueOf(v)
   119  	if reflect.Ptr != valueOf.Kind() {
   120  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
   121  	}
   122  
   123  	if e.Inputs[0].Indexed {
   124  		return fmt.Errorf("abi: attempting to unpack indexed variable into element.")
   125  	}
   126  
   127  	value := valueOf.Elem()
   128  
   129  	marshalledValue, err := toGoType(0, e.Inputs[0].Type, output)
   130  	if err != nil {
   131  		return err
   132  	}
   133  	if err := set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]); err != nil {
   134  		return err
   135  	}
   136  	return nil
   137  }