github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/event_test.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2016 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package abi
    26  
    27  import (
    28  	"bytes"
    29  	"encoding/hex"
    30  	"encoding/json"
    31  	"math/big"
    32  	"reflect"
    33  	"strings"
    34  	"testing"
    35  
    36  	"github.com/ethereum/go-ethereum/common"
    37  	"github.com/ethereum/go-ethereum/crypto"
    38  	"github.com/stretchr/testify/assert"
    39  	"github.com/stretchr/testify/require"
    40  )
    41  
    42  var jsonEventTransfer = []byte(`{
    43    "anonymous": false,
    44    "inputs": [
    45      {
    46        "indexed": true, "name": "from", "type": "address"
    47      }, {
    48        "indexed": true, "name": "to", "type": "address"
    49      }, {
    50        "indexed": false, "name": "value", "type": "uint256"
    51    }],
    52    "name": "Transfer",
    53    "type": "event"
    54  }`)
    55  
    56  var jsonEventPledge = []byte(`{
    57    "anonymous": false,
    58    "inputs": [{
    59        "indexed": false, "name": "who", "type": "address"
    60      }, {
    61        "indexed": false, "name": "wad", "type": "uint128"
    62      }, {
    63        "indexed": false, "name": "currency", "type": "bytes3"
    64    }],
    65    "name": "Pledge",
    66    "type": "event"
    67  }`)
    68  
    69  var jsonEventMixedCase = []byte(`{
    70  	"anonymous": false,
    71  	"inputs": [{
    72  		"indexed": false, "name": "value", "type": "uint256"
    73  	  }, {
    74  		"indexed": false, "name": "_value", "type": "uint256"
    75  	  }, {
    76  		"indexed": false, "name": "Value", "type": "uint256"
    77  	}],
    78  	"name": "MixedCase",
    79  	"type": "event"
    80    }`)
    81  
    82  //一百万
    83  var transferData1 = "00000000000000000000000000000000000000000000000000000000000f4240"
    84  
    85  //“0x00CE0D46D924CC8437C806721496599FC3FA268”,2218516807680,“美元”
    86  var pledgeData1 = "00000000000000000000000000ce0d46d924cc8437c806721496599fc3ffa2680000000000000000000000000000000000000000000000000000020489e800007573640000000000000000000000000000000000000000000000000000000000"
    87  
    88  //1000万22185168076801000001
    89  var mixedCaseData1 = "00000000000000000000000000000000000000000000000000000000000f42400000000000000000000000000000000000000000000000000000020489e8000000000000000000000000000000000000000000000000000000000000000f4241"
    90  
    91  func TestEventId(t *testing.T) {
    92  	var table = []struct {
    93  		definition   string
    94  		expectations map[string]common.Hash
    95  	}{
    96  		{
    97  			definition: `[
    98  			{ "type" : "event", "name" : "balance", "inputs": [{ "name" : "in", "type": "uint256" }] },
    99  			{ "type" : "event", "name" : "check", "inputs": [{ "name" : "t", "type": "address" }, { "name": "b", "type": "uint256" }] }
   100  			]`,
   101  			expectations: map[string]common.Hash{
   102  				"balance": crypto.Keccak256Hash([]byte("balance(uint256)")),
   103  				"check":   crypto.Keccak256Hash([]byte("check(address,uint256)")),
   104  			},
   105  		},
   106  	}
   107  
   108  	for _, test := range table {
   109  		abi, err := JSON(strings.NewReader(test.definition))
   110  		if err != nil {
   111  			t.Fatal(err)
   112  		}
   113  
   114  		for name, event := range abi.Events {
   115  			if event.Id() != test.expectations[name] {
   116  				t.Errorf("expected id to be %x, got %x", test.expectations[name], event.Id())
   117  			}
   118  		}
   119  	}
   120  }
   121  
   122  //TestEventMultiValueWithArrayUnpack验证分析数组后是否将对数组字段进行计数。
   123  func TestEventMultiValueWithArrayUnpack(t *testing.T) {
   124  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
   125  	type testStruct struct {
   126  		Value1 [2]uint8
   127  		Value2 uint8
   128  	}
   129  	abi, err := JSON(strings.NewReader(definition))
   130  	require.NoError(t, err)
   131  	var b bytes.Buffer
   132  	var i uint8 = 1
   133  	for ; i <= 3; i++ {
   134  		b.Write(packNum(reflect.ValueOf(i)))
   135  	}
   136  	var rst testStruct
   137  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   138  	require.Equal(t, [2]uint8{1, 2}, rst.Value1)
   139  	require.Equal(t, uint8(3), rst.Value2)
   140  }
   141  
   142  func TestEventTupleUnpack(t *testing.T) {
   143  
   144  	type EventTransfer struct {
   145  		Value *big.Int
   146  	}
   147  
   148  	type EventTransferWithTag struct {
   149  //这是有效的,因为“value”不可导出,
   150  //因此,值只能解编为“value1”。
   151  		value  *big.Int
   152  		Value1 *big.Int `abi:"value"`
   153  	}
   154  
   155  	type BadEventTransferWithSameFieldAndTag struct {
   156  		Value  *big.Int
   157  		Value1 *big.Int `abi:"value"`
   158  	}
   159  
   160  	type BadEventTransferWithDuplicatedTag struct {
   161  		Value1 *big.Int `abi:"value"`
   162  		Value2 *big.Int `abi:"value"`
   163  	}
   164  
   165  	type BadEventTransferWithEmptyTag struct {
   166  		Value *big.Int `abi:""`
   167  	}
   168  
   169  	type EventPledge struct {
   170  		Who      common.Address
   171  		Wad      *big.Int
   172  		Currency [3]byte
   173  	}
   174  
   175  	type BadEventPledge struct {
   176  		Who      string
   177  		Wad      int
   178  		Currency [3]byte
   179  	}
   180  
   181  	type EventMixedCase struct {
   182  		Value1 *big.Int `abi:"value"`
   183  		Value2 *big.Int `abi:"_value"`
   184  		Value3 *big.Int `abi:"Value"`
   185  	}
   186  
   187  	bigint := new(big.Int)
   188  	bigintExpected := big.NewInt(1000000)
   189  	bigintExpected2 := big.NewInt(2218516807680)
   190  	bigintExpected3 := big.NewInt(1000001)
   191  	addr := common.HexToAddress("0x00Ce0d46d924CC8437c806721496599FC3FFA268")
   192  	var testCases = []struct {
   193  		data     string
   194  		dest     interface{}
   195  		expected interface{}
   196  		jsonLog  []byte
   197  		error    string
   198  		name     string
   199  	}{{
   200  		transferData1,
   201  		&EventTransfer{},
   202  		&EventTransfer{Value: bigintExpected},
   203  		jsonEventTransfer,
   204  		"",
   205  		"Can unpack ERC20 Transfer event into structure",
   206  	}, {
   207  		transferData1,
   208  		&[]interface{}{&bigint},
   209  		&[]interface{}{&bigintExpected},
   210  		jsonEventTransfer,
   211  		"",
   212  		"Can unpack ERC20 Transfer event into slice",
   213  	}, {
   214  		transferData1,
   215  		&EventTransferWithTag{},
   216  		&EventTransferWithTag{Value1: bigintExpected},
   217  		jsonEventTransfer,
   218  		"",
   219  		"Can unpack ERC20 Transfer event into structure with abi: tag",
   220  	}, {
   221  		transferData1,
   222  		&BadEventTransferWithDuplicatedTag{},
   223  		&BadEventTransferWithDuplicatedTag{},
   224  		jsonEventTransfer,
   225  		"struct: abi tag in 'Value2' already mapped",
   226  		"Can not unpack ERC20 Transfer event with duplicated abi tag",
   227  	}, {
   228  		transferData1,
   229  		&BadEventTransferWithSameFieldAndTag{},
   230  		&BadEventTransferWithSameFieldAndTag{},
   231  		jsonEventTransfer,
   232  		"abi: multiple variables maps to the same abi field 'value'",
   233  		"Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable",
   234  	}, {
   235  		transferData1,
   236  		&BadEventTransferWithEmptyTag{},
   237  		&BadEventTransferWithEmptyTag{},
   238  		jsonEventTransfer,
   239  		"struct: abi tag in 'Value' is empty",
   240  		"Can not unpack ERC20 Transfer event with an empty tag",
   241  	}, {
   242  		pledgeData1,
   243  		&EventPledge{},
   244  		&EventPledge{
   245  			addr,
   246  			bigintExpected2,
   247  			[3]byte{'u', 's', 'd'}},
   248  		jsonEventPledge,
   249  		"",
   250  		"Can unpack Pledge event into structure",
   251  	}, {
   252  		pledgeData1,
   253  		&[]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   254  		&[]interface{}{
   255  			&addr,
   256  			&bigintExpected2,
   257  			&[3]byte{'u', 's', 'd'}},
   258  		jsonEventPledge,
   259  		"",
   260  		"Can unpack Pledge event into slice",
   261  	}, {
   262  		pledgeData1,
   263  		&[3]interface{}{&common.Address{}, &bigint, &[3]byte{}},
   264  		&[3]interface{}{
   265  			&addr,
   266  			&bigintExpected2,
   267  			&[3]byte{'u', 's', 'd'}},
   268  		jsonEventPledge,
   269  		"",
   270  		"Can unpack Pledge event into an array",
   271  	}, {
   272  		pledgeData1,
   273  		&[]interface{}{new(int), 0, 0},
   274  		&[]interface{}{},
   275  		jsonEventPledge,
   276  		"abi: cannot unmarshal common.Address in to int",
   277  		"Can not unpack Pledge event into slice with wrong types",
   278  	}, {
   279  		pledgeData1,
   280  		&BadEventPledge{},
   281  		&BadEventPledge{},
   282  		jsonEventPledge,
   283  		"abi: cannot unmarshal common.Address in to string",
   284  		"Can not unpack Pledge event into struct with wrong filed types",
   285  	}, {
   286  		pledgeData1,
   287  		&[]interface{}{common.Address{}, new(big.Int)},
   288  		&[]interface{}{},
   289  		jsonEventPledge,
   290  		"abi: insufficient number of elements in the list/array for unpack, want 3, got 2",
   291  		"Can not unpack Pledge event into too short slice",
   292  	}, {
   293  		pledgeData1,
   294  		new(map[string]interface{}),
   295  		&[]interface{}{},
   296  		jsonEventPledge,
   297  		"abi: cannot unmarshal tuple into map[string]interface {}",
   298  		"Can not unpack Pledge event into map",
   299  	}, {
   300  		mixedCaseData1,
   301  		&EventMixedCase{},
   302  		&EventMixedCase{Value1: bigintExpected, Value2: bigintExpected2, Value3: bigintExpected3},
   303  		jsonEventMixedCase,
   304  		"",
   305  		"Can unpack abi variables with mixed case",
   306  	}}
   307  
   308  	for _, tc := range testCases {
   309  		assert := assert.New(t)
   310  		tc := tc
   311  		t.Run(tc.name, func(t *testing.T) {
   312  			err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
   313  			if tc.error == "" {
   314  				assert.Nil(err, "Should be able to unpack event data.")
   315  				assert.Equal(tc.expected, tc.dest, tc.name)
   316  			} else {
   317  				assert.EqualError(err, tc.error, tc.name)
   318  			}
   319  		})
   320  	}
   321  }
   322  
   323  func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, assert *assert.Assertions) error {
   324  	data, err := hex.DecodeString(hexData)
   325  	assert.NoError(err, "Hex data should be a correct hex-string")
   326  	var e Event
   327  	assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI")
   328  	a := ABI{Events: map[string]Event{"e": e}}
   329  	return a.Unpack(dest, "e", data)
   330  }
   331  
   332  /*
   333  取自
   334  https://github.com/ethereum/go-ethereum/pull/15568
   335  **/
   336  
   337  
   338  type testResult struct {
   339  	Values [2]*big.Int
   340  	Value1 *big.Int
   341  	Value2 *big.Int
   342  }
   343  
   344  type testCase struct {
   345  	definition string
   346  	want       testResult
   347  }
   348  
   349  func (tc testCase) encoded(intType, arrayType Type) []byte {
   350  	var b bytes.Buffer
   351  	if tc.want.Value1 != nil {
   352  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value1))
   353  		b.Write(val)
   354  	}
   355  
   356  	if !reflect.DeepEqual(tc.want.Values, [2]*big.Int{nil, nil}) {
   357  		val, _ := arrayType.pack(reflect.ValueOf(tc.want.Values))
   358  		b.Write(val)
   359  	}
   360  	if tc.want.Value2 != nil {
   361  		val, _ := intType.pack(reflect.ValueOf(tc.want.Value2))
   362  		b.Write(val)
   363  	}
   364  	return b.Bytes()
   365  }
   366  
   367  //TestEventUnpackIndexed验证事件解码器是否将跳过索引字段。
   368  func TestEventUnpackIndexed(t *testing.T) {
   369  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]`
   370  	type testStruct struct {
   371  		Value1 uint8
   372  		Value2 uint8
   373  	}
   374  	abi, err := JSON(strings.NewReader(definition))
   375  	require.NoError(t, err)
   376  	var b bytes.Buffer
   377  	b.Write(packNum(reflect.ValueOf(uint8(8))))
   378  	var rst testStruct
   379  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   380  	require.Equal(t, uint8(0), rst.Value1)
   381  	require.Equal(t, uint8(8), rst.Value2)
   382  }
   383  
   384  //testeventindexedwitharrayunback验证静态数组为索引输入时解码器不会覆盖。
   385  func TestEventIndexedWithArrayUnpack(t *testing.T) {
   386  	definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]`
   387  	type testStruct struct {
   388  		Value1 [2]uint8
   389  		Value2 string
   390  	}
   391  	abi, err := JSON(strings.NewReader(definition))
   392  	require.NoError(t, err)
   393  	var b bytes.Buffer
   394  	stringOut := "abc"
   395  //将被编码的字段数*32
   396  	b.Write(packNum(reflect.ValueOf(32)))
   397  	b.Write(packNum(reflect.ValueOf(len(stringOut))))
   398  	b.Write(common.RightPadBytes([]byte(stringOut), 32))
   399  
   400  	var rst testStruct
   401  	require.NoError(t, abi.Unpack(&rst, "test", b.Bytes()))
   402  	require.Equal(t, [2]uint8{0, 0}, rst.Value1)
   403  	require.Equal(t, stringOut, rst.Value2)
   404  }