github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:26</date> 10 //</624342583497199616> 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 //TestEventMultiValueWithArrayUnpack验证分析数组后是否将对数组字段进行计数。 111 func TestEventMultiValueWithArrayUnpack(t *testing.T) { 112 definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": false, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` 113 type testStruct struct { 114 Value1 [2]uint8 115 Value2 uint8 116 } 117 abi, err := JSON(strings.NewReader(definition)) 118 require.NoError(t, err) 119 var b bytes.Buffer 120 var i uint8 = 1 121 for ; i <= 3; i++ { 122 b.Write(packNum(reflect.ValueOf(i))) 123 } 124 var rst testStruct 125 require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) 126 require.Equal(t, [2]uint8{1, 2}, rst.Value1) 127 require.Equal(t, uint8(3), rst.Value2) 128 } 129 130 func TestEventTupleUnpack(t *testing.T) { 131 132 type EventTransfer struct { 133 Value *big.Int 134 } 135 136 type EventTransferWithTag struct { 137 //这是有效的,因为“value”不可导出, 138 //因此,值只能解编为“value1”。 139 value *big.Int 140 Value1 *big.Int `abi:"value"` 141 } 142 143 type BadEventTransferWithSameFieldAndTag struct { 144 Value *big.Int 145 Value1 *big.Int `abi:"value"` 146 } 147 148 type BadEventTransferWithDuplicatedTag struct { 149 Value1 *big.Int `abi:"value"` 150 Value2 *big.Int `abi:"value"` 151 } 152 153 type BadEventTransferWithEmptyTag struct { 154 Value *big.Int `abi:""` 155 } 156 157 type EventPledge struct { 158 Who common.Address 159 Wad *big.Int 160 Currency [3]byte 161 } 162 163 type BadEventPledge struct { 164 Who string 165 Wad int 166 Currency [3]byte 167 } 168 169 type EventMixedCase struct { 170 Value1 *big.Int `abi:"value"` 171 Value2 *big.Int `abi:"_value"` 172 Value3 *big.Int `abi:"Value"` 173 } 174 175 bigint := new(big.Int) 176 bigintExpected := big.NewInt(1000000) 177 bigintExpected2 := big.NewInt(2218516807680) 178 bigintExpected3 := big.NewInt(1000001) 179 addr := common.HexToAddress("0x00Ce0d46d924CC8437c806721496599FC3FFA268") 180 var testCases = []struct { 181 data string 182 dest interface{} 183 expected interface{} 184 jsonLog []byte 185 error string 186 name string 187 }{{ 188 transferData1, 189 &EventTransfer{}, 190 &EventTransfer{Value: bigintExpected}, 191 jsonEventTransfer, 192 "", 193 "Can unpack ERC20 Transfer event into structure", 194 }, { 195 transferData1, 196 &[]interface{}{&bigint}, 197 &[]interface{}{&bigintExpected}, 198 jsonEventTransfer, 199 "", 200 "Can unpack ERC20 Transfer event into slice", 201 }, { 202 transferData1, 203 &EventTransferWithTag{}, 204 &EventTransferWithTag{Value1: bigintExpected}, 205 jsonEventTransfer, 206 "", 207 "Can unpack ERC20 Transfer event into structure with abi: tag", 208 }, { 209 transferData1, 210 &BadEventTransferWithDuplicatedTag{}, 211 &BadEventTransferWithDuplicatedTag{}, 212 jsonEventTransfer, 213 "struct: abi tag in 'Value2' already mapped", 214 "Can not unpack ERC20 Transfer event with duplicated abi tag", 215 }, { 216 transferData1, 217 &BadEventTransferWithSameFieldAndTag{}, 218 &BadEventTransferWithSameFieldAndTag{}, 219 jsonEventTransfer, 220 "abi: multiple variables maps to the same abi field 'value'", 221 "Can not unpack ERC20 Transfer event with a field and a tag mapping to the same abi variable", 222 }, { 223 transferData1, 224 &BadEventTransferWithEmptyTag{}, 225 &BadEventTransferWithEmptyTag{}, 226 jsonEventTransfer, 227 "struct: abi tag in 'Value' is empty", 228 "Can not unpack ERC20 Transfer event with an empty tag", 229 }, { 230 pledgeData1, 231 &EventPledge{}, 232 &EventPledge{ 233 addr, 234 bigintExpected2, 235 [3]byte{'u', 's', 'd'}}, 236 jsonEventPledge, 237 "", 238 "Can unpack Pledge event into structure", 239 }, { 240 pledgeData1, 241 &[]interface{}{&common.Address{}, &bigint, &[3]byte{}}, 242 &[]interface{}{ 243 &addr, 244 &bigintExpected2, 245 &[3]byte{'u', 's', 'd'}}, 246 jsonEventPledge, 247 "", 248 "Can unpack Pledge event into slice", 249 }, { 250 pledgeData1, 251 &[3]interface{}{&common.Address{}, &bigint, &[3]byte{}}, 252 &[3]interface{}{ 253 &addr, 254 &bigintExpected2, 255 &[3]byte{'u', 's', 'd'}}, 256 jsonEventPledge, 257 "", 258 "Can unpack Pledge event into an array", 259 }, { 260 pledgeData1, 261 &[]interface{}{new(int), 0, 0}, 262 &[]interface{}{}, 263 jsonEventPledge, 264 "abi: cannot unmarshal common.Address in to int", 265 "Can not unpack Pledge event into slice with wrong types", 266 }, { 267 pledgeData1, 268 &BadEventPledge{}, 269 &BadEventPledge{}, 270 jsonEventPledge, 271 "abi: cannot unmarshal common.Address in to string", 272 "Can not unpack Pledge event into struct with wrong filed types", 273 }, { 274 pledgeData1, 275 &[]interface{}{common.Address{}, new(big.Int)}, 276 &[]interface{}{}, 277 jsonEventPledge, 278 "abi: insufficient number of elements in the list/array for unpack, want 3, got 2", 279 "Can not unpack Pledge event into too short slice", 280 }, { 281 pledgeData1, 282 new(map[string]interface{}), 283 &[]interface{}{}, 284 jsonEventPledge, 285 "abi: cannot unmarshal tuple into map[string]interface {}", 286 "Can not unpack Pledge event into map", 287 }, { 288 mixedCaseData1, 289 &EventMixedCase{}, 290 &EventMixedCase{Value1: bigintExpected, Value2: bigintExpected2, Value3: bigintExpected3}, 291 jsonEventMixedCase, 292 "", 293 "Can unpack abi variables with mixed case", 294 }} 295 296 for _, tc := range testCases { 297 assert := assert.New(t) 298 tc := tc 299 t.Run(tc.name, func(t *testing.T) { 300 err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert) 301 if tc.error == "" { 302 assert.Nil(err, "Should be able to unpack event data.") 303 assert.Equal(tc.expected, tc.dest, tc.name) 304 } else { 305 assert.EqualError(err, tc.error, tc.name) 306 } 307 }) 308 } 309 } 310 311 func unpackTestEventData(dest interface{}, hexData string, jsonEvent []byte, assert *assert.Assertions) error { 312 data, err := hex.DecodeString(hexData) 313 assert.NoError(err, "Hex data should be a correct hex-string") 314 var e Event 315 assert.NoError(json.Unmarshal(jsonEvent, &e), "Should be able to unmarshal event ABI") 316 a := ABI{Events: map[string]Event{"e": e}} 317 return a.Unpack(dest, "e", data) 318 } 319 320 /* 321 取自 322 https://github.com/ethereum/go-ethereum/pull/15568 323 **/ 324 325 326 type testResult struct { 327 Values [2]*big.Int 328 Value1 *big.Int 329 Value2 *big.Int 330 } 331 332 type testCase struct { 333 definition string 334 want testResult 335 } 336 337 func (tc testCase) encoded(intType, arrayType Type) []byte { 338 var b bytes.Buffer 339 if tc.want.Value1 != nil { 340 val, _ := intType.pack(reflect.ValueOf(tc.want.Value1)) 341 b.Write(val) 342 } 343 344 if !reflect.DeepEqual(tc.want.Values, [2]*big.Int{nil, nil}) { 345 val, _ := arrayType.pack(reflect.ValueOf(tc.want.Values)) 346 b.Write(val) 347 } 348 if tc.want.Value2 != nil { 349 val, _ := intType.pack(reflect.ValueOf(tc.want.Value2)) 350 b.Write(val) 351 } 352 return b.Bytes() 353 } 354 355 //TestEventUnpackIndexed验证事件解码器是否将跳过索引字段。 356 func TestEventUnpackIndexed(t *testing.T) { 357 definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8"},{"indexed": false, "name":"value2", "type":"uint8"}]}]` 358 type testStruct struct { 359 Value1 uint8 360 Value2 uint8 361 } 362 abi, err := JSON(strings.NewReader(definition)) 363 require.NoError(t, err) 364 var b bytes.Buffer 365 b.Write(packNum(reflect.ValueOf(uint8(8)))) 366 var rst testStruct 367 require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) 368 require.Equal(t, uint8(0), rst.Value1) 369 require.Equal(t, uint8(8), rst.Value2) 370 } 371 372 //testeventindexedwitharrayunback验证静态数组为索引输入时解码器不会覆盖。 373 func TestEventIndexedWithArrayUnpack(t *testing.T) { 374 definition := `[{"name": "test", "type": "event", "inputs": [{"indexed": true, "name":"value1", "type":"uint8[2]"},{"indexed": false, "name":"value2", "type":"string"}]}]` 375 type testStruct struct { 376 Value1 [2]uint8 377 Value2 string 378 } 379 abi, err := JSON(strings.NewReader(definition)) 380 require.NoError(t, err) 381 var b bytes.Buffer 382 stringOut := "abc" 383 //将被编码的字段数*32 384 b.Write(packNum(reflect.ValueOf(32))) 385 b.Write(packNum(reflect.ValueOf(len(stringOut)))) 386 b.Write(common.RightPadBytes([]byte(stringOut), 32)) 387 388 var rst testStruct 389 require.NoError(t, abi.Unpack(&rst, "test", b.Bytes())) 390 require.Equal(t, [2]uint8{0, 0}, rst.Value1) 391 require.Equal(t, stringOut, rst.Value2) 392 } 393