github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/encoding/rlp/rlp_test.go (about)

     1  package rlp
     2  
     3  import (
     4  	"math/big"
     5  	"testing"
     6  
     7  	"github.com/hyperledger/burrow/crypto"
     8  	"github.com/hyperledger/burrow/encoding"
     9  
    10  	"github.com/test-go/testify/require"
    11  )
    12  
    13  type testCase struct {
    14  	in  interface{}
    15  	enc []byte
    16  	dec interface{}
    17  }
    18  
    19  type testObject struct {
    20  	Key   string
    21  	Value string
    22  }
    23  
    24  func TestEncoding(t *testing.T) {
    25  
    26  	t.Run("Empty", func(t *testing.T) {
    27  		var tests = []testCase{
    28  			{
    29  				[]byte{},
    30  				[]byte{uint8(StringOffset)},
    31  				[]byte{},
    32  			},
    33  			{
    34  				"",
    35  				[]byte{uint8(StringOffset)},
    36  				[]byte{},
    37  			},
    38  			{
    39  				0,
    40  				[]byte{uint8(StringOffset)},
    41  				[]byte{},
    42  			},
    43  			{
    44  				[]string{},
    45  				[]byte{uint8(SliceOffset)},
    46  				[]byte{},
    47  			},
    48  		}
    49  
    50  		trial(t, tests)
    51  	})
    52  
    53  	t.Run("Bool", func(t *testing.T) {
    54  		var tests = []testCase{
    55  			{
    56  				true,
    57  				[]byte{0x01},
    58  				[]byte{1},
    59  			},
    60  			{
    61  				false,
    62  				[]byte{uint8(StringOffset)},
    63  				[]byte{0},
    64  			},
    65  		}
    66  
    67  		trial(t, tests)
    68  	})
    69  
    70  	t.Run("String", func(t *testing.T) {
    71  		var tests = []testCase{
    72  			{
    73  				[]byte{0, 0},
    74  				[]byte{uint8(StringOffset) + 2, 0, 0},
    75  				[]byte{0, 0},
    76  			},
    77  			{
    78  				[]byte{0x64, 0x6f, 0x67},
    79  				[]byte{0x83, 100, 111, 103},
    80  				[]byte{0x64, 0x6f, 0x67},
    81  			},
    82  			{
    83  				"dog",
    84  				[]byte{0x83, 100, 111, 103},
    85  				[]byte("dog"),
    86  			},
    87  			{
    88  				"hello world",
    89  				[]byte{0x8b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64},
    90  				[]byte("hello world"),
    91  			},
    92  			{
    93  				"Lorem ipsum dolor sit amet, consectetur adipisicing elit",
    94  				[]byte{0xb8, 0x38, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x69, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x69, 0x74},
    95  				[]byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit"),
    96  			},
    97  			{
    98  				[]byte{0x0f},
    99  				[]byte{0x0f},
   100  				[]byte{0x0f},
   101  			},
   102  			{
   103  				[]byte{0x04, 0x00},
   104  				[]byte{0x82, 0x04, 0x00},
   105  				[]byte{0x04, 0x00},
   106  			},
   107  		}
   108  
   109  		trial(t, tests)
   110  	})
   111  
   112  	t.Run("List", func(t *testing.T) {
   113  		var tests = []testCase{
   114  			{
   115  				[]string{"cat", "dog"},
   116  				[]byte{0xc8, 0x83, byte('c'), byte('a'), byte('t'), 0x83, byte('d'), byte('o'), byte('g')},
   117  				[][]byte{[]byte("cat"), []byte("dog")},
   118  			},
   119  			{
   120  				[][]string{{"cat", "dog"}, {"owl"}},
   121  				[]byte{0xce, 0xc8, 0x83, byte('c'), byte('a'), byte('t'), 0x83, byte('d'), byte('o'), byte('g'), 0xc4, 0x83, byte('o'), byte('w'), byte('l')},
   122  				[][]byte{[]byte("cat"), []byte("dog"), []byte("owl")},
   123  			},
   124  		}
   125  
   126  		trial(t, tests)
   127  	})
   128  
   129  	t.Run("Integers", func(t *testing.T) {
   130  		var tests = []testCase{
   131  			{
   132  				[]uint64{23, 233, 30400},
   133  				[]byte{0xc6, 0x17, 0x81, 0xe9, 0x82, 0x76, 0xc0},
   134  				[][]byte{{23}, {233}, {0x76, 0xc0}},
   135  			},
   136  			{
   137  				[]*big.Int{big.NewInt(23), big.NewInt(233), big.NewInt(30400)},
   138  				[]byte{0xc6, 0x17, 0x81, 0xe9, 0x82, 0x76, 0xc0},
   139  				[][]byte{{23}, {233}, {0x76, 0xc0}},
   140  			},
   141  		}
   142  
   143  		trial(t, tests)
   144  	})
   145  
   146  	t.Run("Struct", func(t *testing.T) {
   147  		var tests = []testCase{
   148  			{
   149  				testObject{"foo", "bar"},
   150  				[]byte{0xc8, 0x83, byte('f'), byte('o'), byte('o'), 0x83, byte('b'), byte('a'), byte('r')},
   151  				&testObject{"foo", "bar"},
   152  			},
   153  		}
   154  
   155  		trial(t, tests)
   156  	})
   157  }
   158  
   159  func trial(t *testing.T, tests []testCase) {
   160  	for _, tt := range tests {
   161  		enc, err := Encode(tt.in)
   162  		require.NoError(t, err)
   163  		require.Equal(t, tt.enc, enc, "encoding must match")
   164  
   165  		var dec interface{}
   166  
   167  		switch todo := tt.dec.(type) {
   168  		case []byte:
   169  			dec = make([]byte, len(todo))
   170  		case [][]byte:
   171  			dec = make([][]byte, len(todo))
   172  		case *testObject:
   173  			dec = new(testObject)
   174  		default:
   175  			require.FailNow(t, "dec type unsupported")
   176  		}
   177  
   178  		err = Decode(enc, dec)
   179  		require.NoError(t, err)
   180  		require.Equal(t, tt.dec, dec, "decoding must match")
   181  	}
   182  }
   183  
   184  type pretendTx struct {
   185  	Nonce    uint64 `json:"nonce"`
   186  	GasPrice uint64 `json:"gasPrice"`
   187  	Gas      uint64 `json:"gas"`
   188  	To       []byte `json:"to"`
   189  	Value    uint64 `json:"value"`
   190  	Input    []byte `json:"input"`
   191  
   192  	V *big.Int `json:"v"`
   193  	R []byte   `json:"r"`
   194  	S []byte   `json:"s"`
   195  }
   196  
   197  func TestEthTransaction(t *testing.T) {
   198  	// raw := `f866068609184e72a0008303000094fa3caabc8eefec2b5e2895e5afbf79379e7268a7808025a06d35f407f418737eec80cba738c4301e683cfcecf19bac9a1aeb2316cac19d3ba002935ee46e3b6bd69168b0b07670699d71df5b32d5f66dbca5758bce2431c9e8`
   199  	// data, err := hex.DecodeString(raw)
   200  	// require.NoError(t, err)
   201  
   202  	//input := []interface{}{
   203  	//	uint64(6),              // Nonce
   204  	//	uint64(10000000000000), // GasPrice
   205  	//	uint64(196608),         // Gas
   206  	//	[]byte{250, 60, 170, 188, 142, 239, 236, 43, 94, 40, 149, 229, 175, 191, 121, 55, 158, 114, 104, 167}, // To
   207  	//	uint64(0), // Value
   208  	//	[]byte{},  // Input
   209  	//	uint64(1), // V
   210  	//	uint(0),   // R
   211  	//	uint(0),   // S
   212  	//}
   213  	input := &pretendTx{
   214  		uint64(6),              // Nonce
   215  		uint64(10000000000000), // GasPrice
   216  		uint64(196608),         // Gas
   217  		[]byte{250, 60, 170, 188, 142, 239, 236, 43, 94, 40, 149, 229, 175, 191, 121, 55, 158, 114, 104, 167}, // To
   218  		uint64(0),     // Value
   219  		[]byte{},      // Input
   220  		big.NewInt(1), // V
   221  		[]byte{1},     // R
   222  		[]byte{1},     // S
   223  	}
   224  	data, err := Encode(input)
   225  	require.NoError(t, err)
   226  
   227  	exp := []byte{230, 6, 134, 9, 24, 78, 114, 160, 0, 131, 3, 0, 0, 148, 250, 60, 170, 188, 142, 239, 236, 43, 94, 40, 149, 229, 175, 191, 121, 55, 158, 114, 104, 167, 128, 128, 1, 1, 1}
   228  	require.Equal(t, exp, data)
   229  
   230  	tx := new(pretendTx)
   231  	err = Decode(data, tx)
   232  	require.NoError(t, err)
   233  
   234  	require.Equal(t, input, tx)
   235  }
   236  
   237  func TestBigInts(t *testing.T) {
   238  	type foo struct {
   239  		A *big.Int
   240  		B *big.Int
   241  	}
   242  
   243  	biggun, ok := new(big.Int).SetString("234234238947234789234789234789234", 10)
   244  	require.True(t, ok)
   245  	input := &foo{
   246  		A: biggun,
   247  		B: big.NewInt(34),
   248  	}
   249  
   250  	bs, err := Encode(input)
   251  	require.NoError(t, err)
   252  
   253  	output := new(foo)
   254  	err = Decode(bs, output)
   255  	require.NoError(t, err)
   256  
   257  	require.Equal(t, input, output)
   258  }
   259  
   260  // Order matters for serialisation
   261  type TestRawTx struct {
   262  	Sequence                uint64 `json:"nonce"`
   263  	GasPrice                uint64 `json:"gasPrice"`
   264  	GasLimit                uint64 `json:"gasLimit"`
   265  	dontSerialiseUnexported uint64
   266  	To                      []byte   `json:"to"`
   267  	Amount                  *big.Int `json:"value"`
   268  	Data                    []byte   `json:"data"`
   269  	ChainID                 *big.Int `json:"chainID"`
   270  
   271  	V *big.Int
   272  	R *big.Int
   273  	S *big.Int
   274  }
   275  
   276  func TestEthRawTx(t *testing.T) {
   277  	bigly, ok := new(big.Int).SetString("234589034578907683457689234545678235789003476899", 10)
   278  	require.True(t, ok)
   279  
   280  	to := crypto.Address{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
   281  
   282  	rawTx := &TestRawTx{
   283  		Sequence: 1,
   284  		GasPrice: 1,
   285  		GasLimit: 1,
   286  		To:       to[:],
   287  		Amount:   big.NewInt(232),
   288  		Data:     []byte{1, 3, 4},
   289  		ChainID:  encoding.GetEthChainID("flgoo"),
   290  		V:        big.NewInt(272),
   291  		R:        bigly,
   292  		S:        bigly,
   293  	}
   294  
   295  	bs, err := Encode(rawTx)
   296  	require.NoError(t, err)
   297  
   298  	rawTxOut := new(TestRawTx)
   299  	err = Decode(bs, rawTxOut)
   300  	require.NoError(t, err)
   301  
   302  	require.Equal(t, rawTx, rawTxOut)
   303  }
   304  
   305  func TestEncodeLength(t *testing.T) {
   306  	// Ensure we have the minimal encoding (no leading zeros)
   307  	require.Equal(t, []byte{0xb8, 0xff}, encodeLength(0xff, StringOffset))
   308  }