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  }