github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/accounts/abi/event_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:31</date>
    10  //</624450061966774272>
    11  
    12  
    13  package abi
    14  
    15  import (
    16  	"bytes"
    17  	"encoding/hex"
    18  	"encoding/json"
    19  	"math/big"
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  )
    29  
    30  var jsonEventTransfer = []byte(`{
    31    "anonymous": false,
    32    "inputs": [
    33      {
    34        "indexed": true, "name": "from", "type": "address"
    35      }, {
    36        "indexed": true, "name": "to", "type": "address"
    37      }, {
    38        "indexed": false, "name": "value", "type": "uint256"
    39    }],
    40    "name": "Transfer",
    41    "type": "event"
    42  }`)
    43  
    44  var jsonEventPledge = []byte(`{
    45    "anonymous": false,
    46    "inputs": [{
    47        "indexed": false, "name": "who", "type": "address"
    48      }, {
    49        "indexed": false, "name": "wad", "type": "uint128"
    50      }, {
    51        "indexed": false, "name": "currency", "type": "bytes3"
    52    }],
    53    "name": "Pledge",
    54    "type": "event"
    55  }`)
    56  
    57  var jsonEventMixedCase = []byte(`{
    58  	"anonymous": false,
    59  	"inputs": [{
    60  		"indexed": false, "name": "value", "type": "uint256"
    61  	  }, {
    62  		"indexed": false, "name": "_value", "type": "uint256"
    63  	  }, {
    64  		"indexed": false, "name": "Value", "type": "uint256"
    65  	}],
    66  	"name": "MixedCase",
    67  	"type": "event"
    68    }`)
    69  
    70  //一百万
    71  var transferData1 = "00000000000000000000000000000000000000000000000000000000000f4240"
    72  
    73  //“0x00CE0D46D924CC8437C806721496599FC3FA268”,2218516807680,“美元”
    74  var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa2680000000000000000000000000000000000000000000000000000020489e800007573640000000000000000000000000000000000000000000000000000000000"
    75  
    76  //1000万22185168076801000001
    77  var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241"
    78  
    79  func TestEventId(t *testing.T) {
    80  	var table = []struct {
    81  		definition   string
    82  		expectations map[string]common.Hash
    83  	}{
    84  		{
    85  			definition: `[
    86  			{ "type" : "event", "name" : "Balance", "inputs": [{ "name" : "in", "type": "uint256" }] },
    87  			{ "type" : "event", "name" : "Check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] }
    88  			]`,
    89  			expectations: map[string]common.Hash{
    90  				"Balance": crypto.Keccak256Hash([]byte("Balance(uint256)")),
    91  				"Check":   crypto.Keccak256Hash([]byte("Check(address,uint256)")),
    92  			},
    93  		},
    94  	}
    95  
    96  	for _, test := range table {
    97  		abi, err := JSON(strings.NewReader(test.definition))
    98  		if err != nil {
    99  			t.Fatal(err)
   100  		}
   101  
   102  		for name, event := range abi.Events {
   103  			if event.Id() != test.expectations[name] {
   104  				t.Errorf("expected id to be %x, got %x", test.expectations[name], event.Id())
   105  			}
   106  		}
   107  	}
   108  }
   109  
   110  func TestEventString(t *testing.T) {
   111  	var table = []struct {
   112  		definition   string
   113  		expectations map[string]string
   114  	}{
   115  		{
   116  			definition: `[
   117  			{ "type" : "event", "name" : "Balance", "inputs": [{ "name" : "in", "type": "uint256" }] },
   118  			{ "type" : "event", "name" : "Check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] },
   119  			{ "type" : "event", "name" : "Transfer", "inputs": [{ "name": "from", "type": "address", "indexed": true }, { "name": "to", "type": "address", "indexed": true }, { "name": "value", "type": "uint256" }] }
   120  			]`,
   121  			expectations: map[string]string{
   122  				"Balance":  "event Balance(uint256 in)",
   123  				"Check":    "event Check(address t, uint256 b)",
   124  				"Transfer": "event Transfer(address indexed from, address indexed to, uint256 value)",
   125  			},
   126  		},
   127  	}
   128  
   129  	for _, test := range table {
   130  		abi, err := JSON(strings.NewReader(test.definition))
   131  		if err != nil {
   132  			t.Fatal(err)
   133  		}
   134  
   135  		for name, event := range abi.Events {
   136  			if event.String() != test.expectations[name] {
   137  				t.Errorf("expected string to be %s, got %s", test.expectations[name], event.String())
   138  			}
   139  		}
   140  	}
   141  }
   142  
   143  //TestEventMultiValueWithArrayUnpack验证分析数组后是否将对数组字段进行计数。
   144  func TestEventMultiValueWithArrayUnpack(t *testing.T) {
   145  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
   146  	type testStruct struct {
   147  		Value1 [2]uint8
   148  		Value2 uint8
   149  	}
   150  	abi, err := JSON(strings.NewReader(definition))
   151  	require.NoError(t, err)
   152  	var b bytes.Buffer
   153  	var i uint8 = 1
   154  	for ; i <= 3; i++ {
   155  		b.Write(packNum(reflect.ValueOf(i)))
   156  	}
   157  	var rst testStruct
   158  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   159  	require.Equal(t, [2]uint8{1, 2}, rst.Value1)
   160  	require.Equal(t, uint8(3), rst.Value2)
   161  }
   162  
   163  func TestEventTupleUnpack(t *testing.T) {
   164  
   165  	type EventTransfer struct {
   166  		Value *big.Int
   167  	}
   168  
   169  	type EventTransferWithTag struct {
   170  //这是有效的,因为“value”不可导出,
   171  //因此,值只能解编为“value1”。
   172  		value  *big.Int
   173  		Value1 *big.Int `abi:"value"`
   174  	}
   175  
   176  	type BadEventTransferWithSameFieldAndTag struct {
   177  		Value  *big.Int
   178  		Value1 *big.Int `abi:"value"`
   179  	}
   180  
   181  	type BadEventTransferWithDuplicatedTag struct {
   182  		Value1 *big.Int `abi:"value"`
   183  		Value2 *big.Int `abi:"value"`
   184  	}
   185  
   186  	type BadEventTransferWithEmptyTag struct {
   187  		Value *big.Int `abi:""`
   188  	}
   189  
   190  	type EventPledge struct {
   191  		Who      common.Address
   192  		Wad      *big.Int
   193  		Currency [3]byte
   194  	}
   195  
   196  	type BadEventPledge struct {
   197  		Who      string
   198  		Wad      int
   199  		Currency [3]byte
   200  	}
   201  
   202  	type EventMixedCase struct {
   203  		Value1 *big.Int `abi:"value"`
   204  		Value2 *big.Int `abi:"_value"`
   205  		Value3 *big.Int `abi:"Value"`
   206  	}
   207  
   208  	bigint := new(big.Int)
   209  	bigintExpected := big.NewInt(1000000)
   210  	bigintExpected2 := big.NewInt(2218516807680)
   211  	bigintExpected3 := big.NewInt(1000001)
   212  	addr := common.HexToAddress("0x00Ce0d46d924CC8437c806721496599FC3FFA268")
   213  	var testCases = []struct {
   214  		data     string
   215  		dest     interface{}
   216  		expected interface{}
   217  		jsonLog  []byte
   218  		error    string
   219  		name     string
   220  	}{{
   221  		transferData1,
   222  		&EventTransfer{},
   223  		&EventTransfer{Value: bigintExpected},
   224  		jsonEventTransfer,
   225  		"",
   226  		"Can unpack ERC20 Transfer event into structure",
   227  	}, {
   228  		transferData1,
   229  		&[]interface{}{&bigint},
   230  		&[]interface{}{&bigintExpected},
   231  		jsonEventTransfer,
   232  		"",
   233  		"Can unpack ERC20 Transfer event into slice",
   234  	}, {
   235  		transferData1,
   236  		&EventTransferWithTag{},
   237  		&EventTransferWithTag{Value1: bigintExpected},
   238  		jsonEventTransfer,
   239  		"",
   240  		"Can unpack ERC20 Transfer event into structure with abi: tag",
   241  	}, {
   242  		transferData1,
   243  		&BadEventTransferWithDuplicatedTag{},
   244  		&BadEventTransferWithDuplicatedTag{},
   245  		jsonEventTransfer,
   246  		"struct: abi tag in 'Value2' already mapped",
   247  		"Can not unpack ERC20 Transfer event with duplicated abi tag",
   248  	}, {
   249  		transferData1,
   250  		&BadEventTransferWithSameFieldAndTag{},
   251  		&BadEventTransferWithSameFieldAndTag{},
   252  		jsonEventTransfer,
   253  		"abi: multiple variables maps to the same abi field 'value'",
   254  		"Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable",
   255  	}, {
   256  		transferData1,
   257  		&BadEventTransferWithEmptyTag{},
   258  		&BadEventTransferWithEmptyTag{},
   259  		jsonEventTransfer,
   260  		"struct: abi tag in 'Value' is empty",
   261  		"Can not unpack ERC20 Transfer event with an empty tag",
   262  	}, {
   263  		pledgeData1,
   264  		&EventPledge{},
   265  		&EventPledge{
   266  			addr,
   267  			bigintExpected2,
   268  			[3]byte{'u', 's', 'd'}},
   269  		jsonEventPledge,
   270  		"",
   271  		"Can unpack Pledge event into structure",
   272  	}, {
   273  		pledgeData1,
   274  		&[]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   275  		&[]interface{}{
   276  			&addr,
   277  			&bigintExpected2,
   278  			&[3]byte{'u', 's', 'd'}},
   279  		jsonEventPledge,
   280  		"",
   281  		"Can unpack Pledge event into slice",
   282  	}, {
   283  		pledgeData1,
   284  		&[3]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   285  		&[3]interface{}{
   286  			&addr,
   287  			&bigintExpected2,
   288  			&[3]byte{'u', 's', 'd'}},
   289  		jsonEventPledge,
   290  		"",
   291  		"Can unpack Pledge event into an array",
   292  	}, {
   293  		pledgeData1,
   294  		&[]interface{}{new(int), 0, 0},
   295  		&[]interface{}{},
   296  		jsonEventPledge,
   297  		"abi: cannot unmarshal common.Address in to int",
   298  		"Can not unpack Pledge event into slice with wrong types",
   299  	}, {
   300  		pledgeData1,
   301  		&BadEventPledge{},
   302  		&BadEventPledge{},
   303  		jsonEventPledge,
   304  		"abi: cannot unmarshal common.Address in to string",
   305  		"Can not unpack Pledge event into struct with wrong filed types",
   306  	}, {
   307  		pledgeData1,
   308  		&[]interface{}{common.Address{}, new(big.Int)},
   309  		&[]interface{}{},
   310  		jsonEventPledge,
   311  		"abi: insufficient number of elements in the list/array for unpack, want 3, got 2",
   312  		"Can not unpack Pledge event into too short slice",
   313  	}, {
   314  		pledgeData1,
   315  		new(map[string]interface{}),
   316  		&[]interface{}{},
   317  		jsonEventPledge,
   318  		"abi: cannot unmarshal tuple into map[string]interface {}",
   319  		"Can not unpack Pledge event into map",
   320  	}, {
   321  		mixedCaseData1,
   322  		&EventMixedCase{},
   323  		&EventMixedCase{Value1: bigintExpected, Value2: bigintExpected2, Value3: bigintExpected3},
   324  		jsonEventMixedCase,
   325  		"",
   326  		"Can unpack abi variables with mixed case",
   327  	}}
   328  
   329  	for _, tc := range testCases {
   330  		assert := assert.New(t)
   331  		tc := tc
   332  		t.Run(tc.name, func(t *testing.T) {
   333  			err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
   334  			if tc.error == "" {
   335  				assert.Nil(err, "Should be able to unpack event data.")
   336  				assert.Equal(tc.expected, tc.dest, tc.name)
   337  			} else {
   338  				assert.EqualError(err, tc.error, tc.name)
   339  			}
   340  		})
   341  	}
   342  }
   343  
   344  func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, assert *assert.Assertions) error {
   345  	data, err := hex.DecodeString(hexData)
   346  	assert.NoError(err, "Hex data should be a correct hex-string")
   347  	var e Event
   348  	assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI")
   349  	a := ABI{Events: map[string]Event{"e": e}}
   350  	return a.Unpack(dest, "e", data)
   351  }
   352  
   353  /*
   354  取自
   355  https://github.com/ethereum/go-ethereum/pull/15568
   356  **/
   357  
   358  
   359  type testResult struct {
   360  	Values [2]*big.Int
   361  	Value1 *big.Int
   362  	Value2 *big.Int
   363  }
   364  
   365  type testCase struct {
   366  	definition string
   367  	want       testResult
   368  }
   369  
   370  func (tc testCase) encoded(intType, arrayType Type) []byte {
   371  	var b bytes.Buffer
   372  	if tc.want.Value1 != nil {
   373  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value1))
   374  		b.Write(val)
   375  	}
   376  
   377  	if !reflect.DeepEqual(tc.want.Values, [2]*big.Int{nil, nil}) {
   378  		val, _ := arrayType.pack(reflect.ValueOf(tc.want.Values))
   379  		b.Write(val)
   380  	}
   381  	if tc.want.Value2 != nil {
   382  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value2))
   383  		b.Write(val)
   384  	}
   385  	return b.Bytes()
   386  }
   387  
   388  //TestEventUnpackIndexed验证事件解码器是否将跳过索引字段。
   389  func TestEventUnpackIndexed(t *testing.T) {
   390  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
   391  	type testStruct struct {
   392  		Value1 uint8
   393  		Value2 uint8
   394  	}
   395  	abi, err := JSON(strings.NewReader(definition))
   396  	require.NoError(t, err)
   397  	var b bytes.Buffer
   398  	b.Write(packNum(reflect.ValueOf(uint8(8))))
   399  	var rst testStruct
   400  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   401  	require.Equal(t, uint8(0), rst.Value1)
   402  	require.Equal(t, uint8(8), rst.Value2)
   403  }
   404  
   405  //testeventindexedwitharrayunback验证静态数组为索引输入时解码器不会覆盖。
   406  func TestEventIndexedWithArrayUnpack(t *testing.T) {
   407  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
   408  	type testStruct struct {
   409  		Value1 [2]uint8
   410  		Value2 string
   411  	}
   412  	abi, err := JSON(strings.NewReader(definition))
   413  	require.NoError(t, err)
   414  	var b bytes.Buffer
   415  	stringOut := "abc"
   416  //将被编码的字段数*32
   417  	b.Write(packNum(reflect.ValueOf(32)))
   418  	b.Write(packNum(reflect.ValueOf(len(stringOut))))
   419  	b.Write(common.RightPadBytes([]byte(stringOut), 32))
   420  
   421  	var rst testStruct
   422  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   423  	require.Equal(t, [2]uint8{0, 0}, rst.Value1)
   424  	require.Equal(t, stringOut, rst.Value2)
   425  }
   426