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 }