github.com/datachainlab/burrow@v0.25.0/execution/evm/abi/core_test.go (about) 1 package abi 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "math/big" 7 "strings" 8 "testing" 9 10 "github.com/hyperledger/burrow/logging" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 //To Test: 16 //Bools, Arrays, Addresses, Hashes 17 //Test Packing different things 18 //After that, should be good to go 19 20 func TestPacker(t *testing.T) { 21 for _, test := range []struct { 22 ABI string 23 args []interface{} 24 name string 25 expectedOutput []byte 26 }{ 27 { 28 `[{"constant":false,"inputs":[{"name":"","type":"uint256"}],"name":"UInt","outputs":[],"payable":false,"type":"function"}]`, 29 []interface{}{"1"}, 30 "UInt", 31 pad([]byte{1}, 32, true), 32 }, 33 { 34 `[{"constant":false,"inputs":[{"name":"","type":"int256"}],"name":"Int","outputs":[],"payable":false,"type":"function"}]`, 35 []interface{}{"-1"}, 36 "Int", 37 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 38 }, 39 { 40 `[{"constant":false,"inputs":[{"name":"","type":"bool"}],"name":"Bool","outputs":[],"payable":false,"type":"function"}]`, 41 []interface{}{"true"}, 42 "Bool", 43 pad([]byte{1}, 32, true), 44 }, 45 { 46 `[{"constant":false,"inputs":[{"name":"","type":"string"}],"name":"String","outputs":[],"payable":false,"type":"function"}]`, 47 []interface{}{"marmots"}, 48 "String", 49 append(hexToBytes(t, "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007"), pad([]byte("marmots"), 32, false)...), 50 }, 51 { 52 `[{"constant":false,"inputs":[{"name":"x","type":"bytes32"}],"name":"Bytes32","outputs":[],"payable":false,"type":"function"}]`, 53 []interface{}{"marmatoshi"}, 54 "Bytes32", 55 pad([]byte("marmatoshi"), 32, false), 56 }, 57 { 58 `[{"constant":false,"inputs":[{"name":"","type":"uint8"}],"name":"UInt8","outputs":[],"payable":false,"type":"function"}]`, 59 []interface{}{"1"}, 60 "UInt8", 61 pad([]byte{1}, 32, true), 62 }, 63 { 64 `[{"constant":false,"inputs":[{"name":"","type":"int8"}],"name":"Int8","outputs":[],"payable":false,"type":"function"}]`, 65 []interface{}{"-1"}, 66 "Int8", 67 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 68 }, 69 { 70 `[{"constant":false,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"name":"multiPackUInts","outputs":[],"payable":false,"type":"function"}]`, 71 []interface{}{"1", "1"}, 72 "multiPackUInts", 73 append(pad([]byte{1}, 32, true), pad([]byte{1}, 32, true)...), 74 }, 75 { 76 `[{"constant":false,"inputs":[{"name":"","type":"bool"},{"name":"","type":"bool"}],"name":"multiPackBools","outputs":[],"payable":false,"type":"function"}]`, 77 []interface{}{"true", "false"}, 78 "multiPackBools", 79 append(pad([]byte{1}, 32, true), pad([]byte{0}, 32, true)...), 80 }, 81 { 82 `[{"constant":false,"inputs":[{"name":"","type":"int256"},{"name":"","type":"int256"}],"name":"multiPackInts","outputs":[],"payable":false,"type":"function"}]`, 83 []interface{}{"-1", "-1"}, 84 "multiPackInts", 85 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 86 }, 87 88 { 89 `[{"constant":false,"inputs":[{"name":"","type":"string"},{"name":"","type":"string"}],"name":"multiPackStrings","outputs":[],"payable":false,"type":"function"}]`, 90 []interface{}{"hello", "world"}, 91 "multiPackStrings", 92 append( 93 hexToBytes(t, "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000005"), 94 append(pad([]byte("hello"), 32, false), 95 append(hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000005"), 96 pad([]byte("world"), 32, false)...)...)..., 97 ), 98 }, 99 { 100 `[{"constant":false,"inputs":[],"name":"arrayOfBytes32Pack","inputs":[{"name":"","type":"bytes32[3]"}],"payable":false,"type":"function"}]`, 101 []interface{}{`[den,of,marmots]`}, 102 "arrayOfBytes32Pack", 103 append( 104 pad([]byte("den"), 32, false), 105 append(pad([]byte("of"), 32, false), pad([]byte("marmots"), 32, false)...)..., 106 ), 107 }, 108 { 109 `[{"constant":false,"inputs":[{"name":"","type":"uint256[3]"}],"name":"arrayOfUIntsPack","outputs":[],"payable":false,"type":"function"}]`, 110 []interface{}{"[1,2,3]"}, 111 "arrayOfUIntsPack", 112 hexToBytes(t, "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"), 113 }, 114 { 115 `[{"constant":false,"inputs":[{"name":"","type":"int256[3]"}],"name":"arrayOfIntsPack","outputs":[],"payable":false,"type":"function"}]`, 116 []interface{}{"[-1,-2,-3]"}, 117 "arrayOfIntsPack", 118 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253}, 119 }, 120 { 121 `[{"constant":false,"inputs":[{"name":"","type":"bool[2]"}],"name":"arrayOfBoolsPack","outputs":[],"payable":false,"type":"function"}]`, 122 []interface{}{"[true,false]"}, 123 "arrayOfBoolsPack", 124 append(pad([]byte{1}, 32, true), pad([]byte{0}, 32, true)...), 125 }, 126 } { 127 t.Log(test.args) 128 if output, _, err := EncodeFunctionCall(test.ABI, test.name, logging.NewNoopLogger(), test.args...); err != nil { 129 t.Error("Unexpected error in ", test.name, ": ", err) 130 } else { 131 if !bytes.Equal(output[4:], test.expectedOutput) { 132 t.Errorf("Incorrect output,\n\t expected %v,\n\t got %v", test.expectedOutput, output[4:]) 133 } 134 } 135 } 136 } 137 138 func TestUnpackerString(t *testing.T) { 139 for _, test := range []struct { 140 abi string 141 packed []byte 142 name string 143 expectedOutput []Variable 144 }{ 145 { 146 `[{"constant":true,"inputs":[],"name":"String","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}]`, 147 append(pad(hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000020"), 32, true), append(pad(hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000005"), 32, true), pad([]byte("Hello"), 32, false)...)...), 148 "String", 149 []Variable{ 150 { 151 Name: "0", 152 Value: "Hello", 153 }, 154 }, 155 }, 156 { 157 `[{"constant":true,"inputs":[],"name":"UInt","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}]`, 158 hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000001"), 159 "UInt", 160 []Variable{ 161 { 162 Name: "0", 163 Value: "1", 164 }, 165 }, 166 }, 167 { 168 `[{"constant":false,"inputs":[],"name":"Int","outputs":[{"name":"retVal","type":"int256"}],"payable":false,"type":"function"}]`, 169 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, 170 "Int", 171 []Variable{ 172 { 173 Name: "retVal", 174 Value: "-1", 175 }, 176 }, 177 }, 178 { 179 `[{"constant":true,"inputs":[],"name":"Bool","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}]`, 180 hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000001"), 181 "Bool", 182 []Variable{ 183 { 184 Name: "0", 185 Value: "true", 186 }, 187 }, 188 }, 189 { 190 `[{"constant":true,"inputs":[],"name":"Address","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}]`, 191 hexToBytes(t, "0000000000000000000000001040E6521541DAB4E7EE57F21226DD17CE9F0FB7"), 192 "Address", 193 []Variable{ 194 { 195 Name: "0", 196 Value: "1040E6521541DAB4E7EE57F21226DD17CE9F0FB7", 197 }, 198 }, 199 }, 200 { 201 `[{"constant":false,"inputs":[],"name":"Bytes32","outputs":[{"name":"retBytes","type":"bytes32"}],"payable":false,"type":"function"}]`, 202 pad([]byte("marmatoshi"), 32, true), 203 "Bytes32", 204 []Variable{ 205 { 206 Name: "retBytes", 207 Value: "marmatoshi", 208 }, 209 }, 210 }, 211 { 212 `[{"constant":false,"inputs":[],"name":"multiReturnUIntInt","outputs":[{"name":"","type":"uint256"},{"name":"","type":"int256"}],"payable":false,"type":"function"}]`, 213 append( 214 hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000001"), 215 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}..., 216 ), 217 "multiReturnUIntInt", 218 []Variable{ 219 { 220 Name: "0", 221 Value: "1", 222 }, 223 { 224 Name: "1", 225 Value: "-1", 226 }, 227 }, 228 }, 229 { 230 `[{"constant":false,"inputs":[],"name":"multiReturnMixed","outputs":[{"name":"","type":"string"},{"name":"","type":"uint256"}],"payable":false,"type":"function"}]`, 231 append( 232 hexToBytes(t, "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001"), 233 append(hexToBytes(t, "0000000000000000000000000000000000000000000000000000000000000005"), pad([]byte("Hello"), 32, false)...)..., 234 ), 235 "multiReturnMixed", 236 []Variable{ 237 { 238 Name: "0", 239 Value: "Hello", 240 }, 241 { 242 Name: "1", 243 Value: "1", 244 }, 245 }, 246 }, 247 { 248 `[{"constant":false,"inputs":[],"name":"multiPackBytes32","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"payable":false,"type":"function"}]`, 249 append( 250 pad([]byte("den"), 32, true), 251 append(pad([]byte("of"), 32, true), pad([]byte("marmots"), 32, true)...)..., 252 ), 253 "multiPackBytes32", 254 []Variable{ 255 { 256 Name: "0", 257 Value: "den", 258 }, 259 { 260 Name: "1", 261 Value: "of", 262 }, 263 { 264 Name: "2", 265 Value: "marmots", 266 }, 267 }, 268 }, 269 { 270 `[{"constant":false,"inputs":[],"name":"arrayReturnBytes32","outputs":[{"name":"","type":"bytes32[3]"}],"payable":false,"type":"function"}]`, 271 append( 272 pad([]byte("den"), 32, true), 273 append(pad([]byte("of"), 32, true), pad([]byte("marmots"), 32, true)...)..., 274 ), 275 "arrayReturnBytes32", 276 []Variable{ 277 { 278 Name: "0", 279 Value: "[den,of,marmots]", 280 }, 281 }, 282 }, 283 { 284 `[{"constant":false,"inputs":[],"name":"arrayReturnUInt","outputs":[{"name":"","type":"uint256[3]"}],"payable":false,"type":"function"}]`, 285 hexToBytes(t, "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"), 286 "arrayReturnUInt", 287 []Variable{ 288 { 289 Name: "0", 290 Value: "[1,2,3]", 291 }, 292 }, 293 }, 294 { 295 `[{"constant":false,"inputs":[],"name":"arrayReturnInt","outputs":[{"name":"","type":"int256[2]"}],"payable":false,"type":"function"}]`, 296 []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254}, 297 "arrayReturnInt", 298 []Variable{ 299 { 300 Name: "0", 301 Value: "[-3,-2]", 302 }, 303 }, 304 }, 305 } { 306 //t.Log(test.name) 307 t.Log(test.packed) 308 output, err := DecodeFunctionReturn(test.abi, test.name, test.packed) 309 if err != nil { 310 t.Errorf("Unpacker failed: %v", err) 311 } 312 for i, expectedOutput := range test.expectedOutput { 313 314 if output[i].Name != expectedOutput.Name { 315 t.Errorf("Unpacker failed: Incorrect Name, got %v expected %v", output[i].Name, expectedOutput.Name) 316 } 317 //t.Log("Test: ", output[i].Value) 318 //t.Log("Test: ", expectedOutput.Value) 319 if strings.Compare(output[i].Value, expectedOutput.Value) != 0 { 320 t.Errorf("Unpacker failed: Incorrect value, got %v expected %v", output[i].Value, expectedOutput.Value) 321 } 322 } 323 } 324 } 325 326 func TestUnpacker(t *testing.T) { 327 for _, test := range []struct { 328 evm EVMType 329 packed []byte 330 data interface{} 331 expectedOutput interface{} 332 }{ 333 /* positive numbers */ 334 { 335 EVMInt{M: 256}, 336 pad([]byte{42}, 32, true), 337 new(int64), 338 func() *int64 { var v int64; v = 42; return &v }(), 339 }, 340 { 341 EVMInt{M: 256}, 342 pad([]byte{42}, 32, true), 343 new(int32), 344 func() *int32 { var v int32; v = 42; return &v }(), 345 }, 346 { 347 EVMInt{M: 256}, 348 pad([]byte{0x7f, 0xff}, 32, true), 349 new(int16), 350 func() *int16 { var v int16; v = 0x7fff; return &v }(), 351 }, 352 { 353 EVMInt{M: 256}, 354 pad([]byte{0xfd, 0xca}, 32, true), 355 new(uint16), 356 func() *uint16 { var v uint16; v = 0xfdca; return &v }(), 357 }, 358 { 359 EVMInt{M: 256}, 360 pad([]byte{0xfd, 0xca}, 32, true), 361 new(uint32), 362 func() *uint32 { var v uint32; v = 0xfdca; return &v }(), 363 }, 364 { 365 EVMInt{M: 256}, 366 pad([]byte{0xfd, 0xca, 0, 0, 0, 0, 0, 0}, 32, true), 367 new(uint64), 368 func() *uint64 { var v uint64; v = 0xfdca000000000000; return &v }(), 369 }, 370 { 371 EVMInt{M: 256}, 372 pad([]byte{42}, 32, true), 373 new(big.Int), 374 big.NewInt(42), 375 }, 376 /* Negative numbers */ 377 { 378 EVMInt{M: 256}, 379 hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6"), 380 new(int64), 381 func() *int64 { var v int64; v = -42; return &v }(), 382 }, 383 { 384 EVMInt{M: 256}, 385 hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6"), 386 new(int32), 387 func() *int32 { var v int32; v = -42; return &v }(), 388 }, 389 { 390 EVMInt{M: 256}, 391 hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8001"), 392 new(int16), 393 func() *int16 { var v int16; v = -0x7fff; return &v }(), 394 }, 395 { 396 EVMInt{M: 256}, 397 hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6C20"), 398 new(int32), 399 func() *int32 { var v int32; v = -300000; return &v }(), 400 }, 401 { 402 EVMInt{M: 256}, 403 hexToBytes(t, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35010124111"), 404 new(int64), 405 func() *int64 { var v int64; v = -0xcafefedbeef; return &v }(), 406 }, 407 { 408 EVMInt{M: 256}, 409 hexToBytes(t, "80000000000000000000000000000000000000000000000000000CAFEFEDBEEF"), 410 new(big.Int), 411 func() *big.Int { 412 v := new(big.Int) 413 x, _ := v.SetString("-57896044618658097711785492504343953926634992332820282019728791990006780674321", 10) 414 return x 415 }(), 416 }, 417 { 418 EVMUint{M: 256}, 419 pad([]byte{42}, 32, true), 420 new(int64), 421 func() *int64 { var v int64; v = 42; return &v }(), 422 }, 423 { 424 EVMUint{M: 256}, 425 pad([]byte{42}, 32, true), 426 new(int32), 427 func() *int32 { var v int32; v = 42; return &v }(), 428 }, 429 { 430 EVMUint{M: 256}, 431 pad([]byte{0x7f, 0xff}, 32, true), 432 new(int16), 433 func() *int16 { var v int16; v = 0x7fff; return &v }(), 434 }, 435 { 436 EVMUint{M: 256}, 437 pad([]byte{0xfd, 0xca}, 32, true), 438 new(uint16), 439 func() *uint16 { var v uint16; v = 0xfdca; return &v }(), 440 }, 441 { 442 EVMUint{M: 256}, 443 pad([]byte{0xfd, 0xca}, 32, true), 444 new(uint32), 445 func() *uint32 { var v uint32; v = 0xfdca; return &v }(), 446 }, 447 { 448 EVMUint{M: 256}, 449 pad([]byte{0xfd, 0xca, 0, 0, 0, 0, 0, 0}, 32, true), 450 new(uint64), 451 func() *uint64 { var v uint64; v = 0xfdca000000000000; return &v }(), 452 }, 453 { 454 EVMUint{M: 256}, 455 pad([]byte{42}, 32, true), 456 new(big.Int), 457 big.NewInt(42), 458 }, 459 } { 460 //t.Log(test.name) 461 t.Log(test.packed) 462 _, err := test.evm.unpack(test.packed, 0, test.data) 463 if err != nil { 464 t.Errorf("Unpacker failed: %v", err) 465 } 466 assert.EqualValues(t, test.expectedOutput, test.data) 467 } 468 } 469 470 func hexToBytes(t testing.TB, hexString string) []byte { 471 bs, err := hex.DecodeString(hexString) 472 require.NoError(t, err) 473 return bs 474 }