@@ -20,13 +20,14 @@ let server: SocketCluster;
20
20
let socket ;
21
21
let connect ;
22
22
let emit ;
23
+ let invalidOpcode ;
23
24
let ping ;
24
25
let pong ;
25
26
let send ;
26
27
27
28
const headers = {
28
29
version : "2.1.0" ,
29
- port : " 4009" ,
30
+ port : 4009 ,
30
31
height : 1 ,
31
32
"Content-Type" : "application/json" ,
32
33
} ;
@@ -61,6 +62,7 @@ beforeAll(async () => {
61
62
62
63
ping = ( ) => socket . transport . socket . ping ( ) ;
63
64
pong = ( ) => socket . transport . socket . pong ( ) ;
65
+ invalidOpcode = ( ) => socket . transport . socket . _socket . write ( Buffer . from ( "8780d0b6fbd2" , "hex" ) ) ;
64
66
65
67
jest . spyOn ( processor , "validateAndAcceptPeer" ) . mockImplementation ( jest . fn ( ) ) ;
66
68
} ) ;
@@ -115,14 +117,17 @@ describe("Peer socket endpoint", () => {
115
117
expect ( data ) . toEqual ( { } ) ;
116
118
} ) ;
117
119
118
- it ( "should throw validation error when sending wrong data" , async ( ) => {
120
+ it ( "should throw error when sending wrong data" , async ( ) => {
119
121
await delay ( 1000 ) ;
120
122
await expect (
121
123
emit ( "p2p.peer.postBlock" , {
122
124
data : { } ,
123
125
headers,
124
126
} ) ,
125
- ) . rejects . toHaveProperty ( "name" , "Error" ) ;
127
+ ) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
128
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
129
+ server . killWorkers ( { immediate : true } ) ;
130
+ await delay ( 2000 ) ; // give time to workers to respawn
126
131
} ) ;
127
132
128
133
it ( "should throw error when sending wrong buffer" , async ( ) => {
@@ -134,7 +139,37 @@ describe("Peer socket endpoint", () => {
134
139
} ,
135
140
headers,
136
141
} ) ,
137
- ) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
142
+ ) . rejects . toHaveProperty ( "name" , "Error" ) ;
143
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
144
+ server . killWorkers ( { immediate : true } ) ;
145
+ await delay ( 2000 ) ; // give time to workers to respawn
146
+ } ) ;
147
+
148
+ it ( "should throw error if too many transactions are in the block" , async ( ) => {
149
+ await delay ( 2000 ) ;
150
+ const dummyBlock = BlockFactory . createDummy ( ) ;
151
+ const transaction = TransactionFactory . transfer ( wallets [ 0 ] . address , 111 )
152
+ . withNetwork ( "unitnet" )
153
+ . withPassphrase ( "one two three" )
154
+ . build ( ) ;
155
+
156
+ for ( let i = 0 ; i < 1000 ; i ++ ) {
157
+ dummyBlock . transactions . push ( transaction [ 0 ] ) ;
158
+ }
159
+
160
+ dummyBlock . data . numberOfTransactions = 1000 ;
161
+
162
+ await expect (
163
+ emit ( "p2p.peer.postBlock" , {
164
+ data : {
165
+ block : Blocks . Serializer . serializeWithTransactions ( {
166
+ ...dummyBlock . data ,
167
+ transactions : dummyBlock . transactions . map ( tx => tx . data ) ,
168
+ } ) ,
169
+ } ,
170
+ headers,
171
+ } ) ,
172
+ ) . rejects . toHaveProperty ( "name" , "Error" ) ;
138
173
} ) ;
139
174
} ) ;
140
175
@@ -155,29 +190,30 @@ describe("Peer socket endpoint", () => {
155
190
// because our mocking makes all transactions to be invalid (already in cache)
156
191
} ) ;
157
192
158
- it ( "should throw validation error when sending too much transactions" , async ( ) => {
193
+ it ( "should reject when sending too much transactions" , async ( ) => {
159
194
const transactions = TransactionFactory . transfer ( wallets [ 0 ] . address , 111 )
160
195
. withNetwork ( "unitnet" )
161
196
. withPassphrase ( "one two three" )
162
197
. create ( 50 ) ;
163
198
164
- // TODO: test makes no sense anymore
165
199
await expect (
166
200
emit ( "p2p.peer.postTransactions" , {
167
201
data : { transactions } ,
168
202
headers,
169
203
} ) ,
170
- ) . toResolve ( ) ;
204
+ ) . toReject ( ) ;
205
+
206
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
207
+ server . killWorkers ( { immediate : true } ) ;
208
+ await delay ( 2000 ) ; // give time to workers to respawn
171
209
} ) ;
172
210
173
211
it ( "should disconnect the client if it sends an invalid message payload" , async ( ) => {
212
+ connect ( ) ;
174
213
await delay ( 1000 ) ;
175
214
176
215
expect ( socket . state ) . toBe ( "open" ) ;
177
216
178
- send ( '{"event": "#handshake", "data": {}, "cid": 1}' ) ;
179
- await delay ( 500 ) ;
180
-
181
217
send ( "Invalid payload" ) ;
182
218
await delay ( 1000 ) ;
183
219
@@ -194,9 +230,6 @@ describe("Peer socket endpoint", () => {
194
230
195
231
expect ( socket . state ) . toBe ( "open" ) ;
196
232
197
- send ( '{"event": "#handshake", "data": {}, "cid": 1}' ) ;
198
- await delay ( 500 ) ;
199
-
200
233
send ( "#2" ) ;
201
234
await delay ( 1000 ) ;
202
235
@@ -242,11 +275,58 @@ describe("Peer socket endpoint", () => {
242
275
server . killWorkers ( { immediate : true } ) ;
243
276
await delay ( 2000 ) ; // give time to workers to respawn
244
277
} ) ;
278
+
279
+ it ( "should block the client if it sends an invalid opcode" , async ( ) => {
280
+ connect ( ) ;
281
+ await delay ( 1000 ) ;
282
+
283
+ expect ( socket . state ) . toBe ( "open" ) ;
284
+
285
+ invalidOpcode ( ) ;
286
+ await delay ( 500 ) ;
287
+ expect ( socket . state ) . toBe ( "closed" ) ;
288
+ await delay ( 500 ) ;
289
+ connect ( ) ;
290
+ await delay ( 500 ) ;
291
+ expect ( socket . state ) . toBe ( "closed" ) ;
292
+
293
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
294
+ server . killWorkers ( { immediate : true } ) ;
295
+ await delay ( 2000 ) ; // give time to workers to respawn
296
+ } ) ;
245
297
} ) ;
246
298
} ) ;
247
299
248
300
describe ( "Socket errors" , ( ) => {
301
+ it ( "should disconnect all sockets from same ip if another connection is made from the same IP address" , async ( ) => {
302
+ connect ( ) ;
303
+ await delay ( 1000 ) ;
304
+
305
+ expect ( socket . state ) . toBe ( "open" ) ;
306
+
307
+ const secondSocket = socketCluster . create ( {
308
+ port : 4007 ,
309
+ hostname : "127.0.0.1" ,
310
+ multiplex : false ,
311
+ } ) ;
312
+ secondSocket . on ( "error" , ( ) => {
313
+ //
314
+ } ) ;
315
+
316
+ secondSocket . connect ( ) ;
317
+
318
+ await delay ( 1000 ) ;
319
+
320
+ expect ( socket . state ) . toBe ( "closed" ) ;
321
+ expect ( secondSocket . state ) . toBe ( "open" ) ;
322
+
323
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
324
+ server . killWorkers ( { immediate : true } ) ;
325
+ await delay ( 2000 ) ; // give time to workers to respawn
326
+ } ) ;
327
+
249
328
it ( "should accept the request when below rate limit" , async ( ) => {
329
+ connect ( ) ;
250
330
await delay ( 1000 ) ;
251
331
for ( let i = 0 ; i < 2 ; i ++ ) {
252
332
const { data } = await emit ( "p2p.peer.getStatus" , {
@@ -288,15 +368,16 @@ describe("Peer socket endpoint", () => {
288
368
289
369
const block = BlockFactory . createDummy ( ) ;
290
370
291
- const postBlock = ( ) => emit ( "p2p.peer.postBlock" , {
292
- headers,
293
- data : {
294
- block : Blocks . Serializer . serializeWithTransactions ( {
295
- ...block . data ,
296
- transactions : block . transactions . map ( tx => tx . data ) ,
297
- } ) ,
298
- } ,
299
- } ) ;
371
+ const postBlock = ( ) =>
372
+ emit ( "p2p.peer.postBlock" , {
373
+ headers,
374
+ data : {
375
+ block : Blocks . Serializer . serializeWithTransactions ( {
376
+ ...block . data ,
377
+ transactions : block . transactions . map ( tx => tx . data ) ,
378
+ } ) ,
379
+ } ,
380
+ } ) ;
300
381
301
382
await expect ( postBlock ( ) ) . toResolve ( ) ;
302
383
await expect ( postBlock ( ) ) . toResolve ( ) ;
@@ -326,9 +407,14 @@ describe("Peer socket endpoint", () => {
326
407
} ,
327
408
) ,
328
409
) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
410
+
411
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
412
+ server . killWorkers ( { immediate : true } ) ;
413
+ await delay ( 2000 ) ; // give time to workers to respawn
329
414
} ) ;
330
415
331
416
it ( "should close the connection when the event does not start with p2p" , async ( ) => {
417
+ connect ( ) ;
332
418
await delay ( 1000 ) ;
333
419
334
420
await expect (
@@ -337,9 +423,14 @@ describe("Peer socket endpoint", () => {
337
423
data : { } ,
338
424
} ) ,
339
425
) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
426
+
427
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
428
+ server . killWorkers ( { immediate : true } ) ;
429
+ await delay ( 2000 ) ; // give time to workers to respawn
340
430
} ) ;
341
431
342
432
it ( "should close the connection when the version is invalid" , async ( ) => {
433
+ connect ( ) ;
343
434
await delay ( 1000 ) ;
344
435
345
436
await expect (
@@ -348,9 +439,13 @@ describe("Peer socket endpoint", () => {
348
439
data : { } ,
349
440
} ) ,
350
441
) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
442
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
443
+ server . killWorkers ( { immediate : true } ) ;
444
+ await delay ( 2000 ) ; // give time to workers to respawn
351
445
} ) ;
352
446
353
447
it ( "should close the connection and prevent reconnection if blocked" , async ( ) => {
448
+ connect ( ) ;
354
449
await delay ( 1000 ) ;
355
450
356
451
await emit ( "p2p.peer.getPeers" , {
@@ -375,6 +470,25 @@ describe("Peer socket endpoint", () => {
375
470
await delay ( 1000 ) ;
376
471
377
472
expect ( socket . state ) . not . toBe ( "open" ) ;
473
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
474
+ server . killWorkers ( { immediate : true } ) ;
475
+ await delay ( 2000 ) ; // give time to workers to respawn
476
+ } ) ;
477
+
478
+ it ( "should close the connection when using unsupported event messages" , async ( ) => {
479
+ connect ( ) ;
480
+ await delay ( 1000 ) ;
481
+
482
+ await expect (
483
+ emit ( "#subscribe" , {
484
+ headers,
485
+ data : { } ,
486
+ } ) ,
487
+ ) . rejects . toHaveProperty ( "name" , "BadConnectionError" ) ;
488
+
489
+ // kill workers to reset ipLastError (or we won't pass handshake for 1 minute)
490
+ server . killWorkers ( { immediate : true } ) ;
491
+ await delay ( 2000 ) ; // give time to workers to respawn
378
492
} ) ;
379
493
380
494
it ( "should close the connection if it sends data after a disconnect packet" , async ( ) => {
@@ -394,5 +508,31 @@ describe("Peer socket endpoint", () => {
394
508
server . killWorkers ( { immediate : true } ) ;
395
509
await delay ( 2000 ) ; // give time to workers to respawn
396
510
} ) ;
511
+
512
+ it ( "should close the connection when the JSON includes additional properties" , async ( ) => {
513
+ connect ( ) ;
514
+ await delay ( 1000 ) ;
515
+ const payload : any = { } ;
516
+ payload . event = "p2p.peer.getCommonBlocks" ;
517
+ payload . data = { data : { ids : [ "1" ] } , headers : { } } ;
518
+ payload . cid = 1 ;
519
+
520
+ const symbol = String . fromCharCode ( 42 ) ;
521
+ for ( let i = 0 ; i < 30000 ; i ++ ) {
522
+ const char = String . fromCharCode ( i ) ;
523
+ if ( JSON . stringify ( String . fromCharCode ( i ) ) . length === 3 ) {
524
+ payload . data [ char ] = 1 ;
525
+ payload . data [ symbol + char ] = 1 ;
526
+ payload . data [ symbol + char + symbol ] = 1 ;
527
+ payload . data [ char ] = 1 ;
528
+ }
529
+ }
530
+
531
+ const stringifiedPayload = JSON . stringify ( payload ) . replace ( / / g, "" ) ;
532
+ expect ( socket . state ) . toBe ( "open" ) ;
533
+ send ( stringifiedPayload ) ;
534
+ await delay ( 500 ) ;
535
+ expect ( socket . state ) . not . toBe ( "open" ) ;
536
+ } ) ;
397
537
} ) ;
398
538
} ) ;
0 commit comments