1- import each from 'jest-each' ;
21import { CallServiceData } from '../../internal/commonTypes' ;
3- import { defaultServices } from '../../internal/defaultServices' ;
4-
5- describe ( 'Tests for default handler' , ( ) => {
6- // prettier-ignore
7- each `
8- serviceId | fnName | args | retCode | result
9- ${ 'op' } | ${ 'identity' } | ${ [ ] } | ${ 0 } | ${ { } }
10- ${ 'op' } | ${ 'identity' } | ${ [ 1 ] } | ${ 0 } | ${ 1 }
11- ${ 'op' } | ${ 'identity' } | ${ [ 1 , 2 ] } | ${ 1 } | ${ 'identity accepts up to 1 arguments, received 2 arguments' }
12-
13- ${ 'op' } | ${ 'noop' } | ${ [ 1 , 2 ] } | ${ 0 } | ${ { } }
14-
15- ${ 'op' } | ${ 'array' } | ${ [ 1 , 2 , 3 ] } | ${ 0 } | ${ [ 1 , 2 , 3 ] }
2+ import each from 'jest-each' ;
3+ import { BuiltInServiceContext , builtInServices } from '../../internal/builtInServices' ;
4+ import { KeyPair } from '../../internal/KeyPair' ;
5+ import { toUint8Array } from 'js-base64' ;
166
17- ${ 'op' } | ${ 'concat' } | ${ [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] } | ${ 0 } | ${ [ 1 , 2 , 3 , 4 , 5 , 6 ] }
18- ${ 'op' } | ${ 'concat' } | ${ [ [ 1 , 2 ] ] } | ${ 0 } | ${ [ 1 , 2 ] }
19- ${ 'op' } | ${ 'concat' } | ${ [ ] } | ${ 0 } | ${ [ ] }
20- ${ 'op' } | ${ 'concat' } | ${ [ 1 , [ 1 , 2 ] , 1 ] } | ${ 1 } | ${ "All arguments of 'concat' must be arrays: arguments 0, 2 are not" }
7+ const key = '+cmeYlZKj+MfSa9dpHV+BmLPm6wq4inGlsPlQ1GvtPk=' ;
218
22- ${ 'op' } | ${ 'string_to_b58' } | ${ [ "test" ] } | ${ 0 } | ${ "3yZe7d" }
23- ${ 'op' } | ${ 'string_to_b58' } | ${ [ "test" , 1 ] } | ${ 1 } | ${ "string_to_b58 accepts only one string argument" }
9+ const context = ( async ( ) => {
10+ const keyBytes = toUint8Array ( key ) ;
11+ const kp = await KeyPair . fromEd25519SK ( keyBytes ) ;
12+ const res : BuiltInServiceContext = {
13+ peerKeyPair : kp ,
14+ peerId : kp . Libp2pPeerId . toB58String ( ) ,
15+ } ;
16+ return res ;
17+ } ) ( ) ;
2418
25- ${ 'op' } | ${ 'string_from_b58' } | ${ [ "3yZe7d" ] } | ${ 0 } | ${ "test" }
26- ${ 'op' } | ${ 'string_from_b58' } | ${ [ "3yZe7d" , 1 ] } | ${ 1 } | ${ "string_from_b58 accepts only one string argument" }
19+ const testData = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 9 , 10 ] ;
2720
28- ${ 'op' } | ${ 'bytes_to_b58' } | ${ [ [ 116 , 101 , 115 , 116 ] ] } | ${ 0 } | ${ "3yZe7d" }
29- ${ 'op' } | ${ 'bytes_to_b58' } | ${ [ [ 116 , 101 , 115 , 116 ] , 1 ] } | ${ 1 } | ${ "bytes_to_b58 accepts only single argument: array of numbers" }
21+ // signature produced by KeyPair created from key above (`key` variable)
22+ const testDataSig = [
23+ 224 , 104 , 245 , 206 , 140 , 248 , 27 , 72 , 68 , 133 , 111 , 10 , 164 , 197 , 242 , 132 , 107 , 77 , 224 , 67 , 99 , 106 , 76 , 29 , 144 ,
24+ 121 , 122 , 169 , 36 , 173 , 58 , 80 , 170 , 102 , 137 , 253 , 157 , 247 , 168 , 87 , 162 , 223 , 188 , 214 , 203 , 220 , 52 , 246 , 29 ,
25+ 86 , 77 , 71 , 224 , 248 , 16 , 213 , 254 , 75 , 78 , 239 , 243 , 222 , 241 , 15 ,
26+ ] ;
3027
31- ${ 'op' } | ${ 'bytes_from_b58' } | ${ [ "3yZe7d" ] } | ${ 0 } | ${ [ 116 , 101 , 115 , 116 ] }
32- ${ 'op' } | ${ 'bytes_from_b58' } | ${ [ "3yZe7d" , 1 ] } | ${ 1 } | ${ "bytes_from_b58 accepts only one string argument" }
28+ // signature produced by KeyPair created from some random KeyPair
29+ const testDataWrongSig = [
30+ 116 , 247 , 189 , 118 , 236 , 53 , 147 , 123 , 219 , 75 , 176 , 105 , 101 , 108 , 233 , 137 , 97 , 14 , 146 , 132 , 252 , 70 , 51 , 153 ,
31+ 237 , 167 , 156 , 150 , 36 , 90 , 229 , 108 , 166 , 231 , 255 , 137 , 8 , 246 , 125 , 0 , 213 , 150 , 83 , 196 , 237 , 221 , 131 , 159 ,
32+ 157 , 159 , 25 , 109 , 95 , 160 , 181 , 65 , 254 , 238 , 47 , 156 , 240 , 151 , 58 , 14 ,
33+ ] ;
3334
34- ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , [ ] ] } | ${ 0 } | ${ [ ] } }
35- ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , [ 'test' ] ] } | ${ 0 } | ${ [ 'test' ] } }
36- ${ 'peer' } | ${ 'timeout' } | ${ [ ] } | ${ 1 } | ${ 'timeout accepts exactly two arguments: timeout duration in ms and a message string' } }
37- ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , 'test' , 1 ] } | ${ 1 } | ${ 'timeout accepts exactly two arguments: timeout duration in ms and a message string' } }
38-
35+ describe ( 'Tests for default handler' , ( ) => {
36+ // prettier-ignore
37+ each `
38+ serviceId | fnName | args | retCode | result
39+ ${ 'op' } | ${ 'identity' } | ${ [ ] } | ${ 0 } | ${ { } }
40+ ${ 'op' } | ${ 'identity' } | ${ [ 1 ] } | ${ 0 } | ${ 1 }
41+ ${ 'op' } | ${ 'identity' } | ${ [ 1 , 2 ] } | ${ 1 } | ${ 'identity accepts up to 1 arguments, received 2 arguments' }
42+
43+ ${ 'op' } | ${ 'noop' } | ${ [ 1 , 2 ] } | ${ 0 } | ${ { } }
44+
45+ ${ 'op' } | ${ 'array' } | ${ [ 1 , 2 , 3 ] } | ${ 0 } | ${ [ 1 , 2 , 3 ] }
46+
47+ ${ 'op' } | ${ 'concat' } | ${ [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] } | ${ 0 } | ${ [ 1 , 2 , 3 , 4 , 5 , 6 ] }
48+ ${ 'op' } | ${ 'concat' } | ${ [ [ 1 , 2 ] ] } | ${ 0 } | ${ [ 1 , 2 ] }
49+ ${ 'op' } | ${ 'concat' } | ${ [ ] } | ${ 0 } | ${ [ ] }
50+ ${ 'op' } | ${ 'concat' } | ${ [ 1 , [ 1 , 2 ] , 1 ] } | ${ 1 } | ${ "All arguments of 'concat' must be arrays: arguments 0, 2 are not" }
51+
52+ ${ 'op' } | ${ 'string_to_b58' } | ${ [ "test" ] } | ${ 0 } | ${ "3yZe7d" }
53+ ${ 'op' } | ${ 'string_to_b58' } | ${ [ "test" , 1 ] } | ${ 1 } | ${ "string_to_b58 accepts only one string argument" }
54+
55+ ${ 'op' } | ${ 'string_from_b58' } | ${ [ "3yZe7d" ] } | ${ 0 } | ${ "test" }
56+ ${ 'op' } | ${ 'string_from_b58' } | ${ [ "3yZe7d" , 1 ] } | ${ 1 } | ${ "string_from_b58 accepts only one string argument" }
57+
58+ ${ 'op' } | ${ 'bytes_to_b58' } | ${ [ [ 116 , 101 , 115 , 116 ] ] } | ${ 0 } | ${ "3yZe7d" }
59+ ${ 'op' } | ${ 'bytes_to_b58' } | ${ [ [ 116 , 101 , 115 , 116 ] , 1 ] } | ${ 1 } | ${ "bytes_to_b58 accepts only single argument: array of numbers" }
60+
61+ ${ 'op' } | ${ 'bytes_from_b58' } | ${ [ "3yZe7d" ] } | ${ 0 } | ${ [ 116 , 101 , 115 , 116 ] }
62+ ${ 'op' } | ${ 'bytes_from_b58' } | ${ [ "3yZe7d" , 1 ] } | ${ 1 } | ${ "bytes_from_b58 accepts only one string argument" }
63+
64+ ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , [ ] ] } | ${ 0 } | ${ [ ] } }
65+ ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , [ 'test' ] ] } | ${ 0 } | ${ [ 'test' ] } }
66+ ${ 'peer' } | ${ 'timeout' } | ${ [ ] } | ${ 1 } | ${ 'timeout accepts exactly two arguments: timeout duration in ms and a message string' } }
67+ ${ 'peer' } | ${ 'timeout' } | ${ [ 200 , 'test' , 1 ] } | ${ 1 } | ${ 'timeout accepts exactly two arguments: timeout duration in ms and a message string' } }
68+
69+ ${ 'sig' } | ${ 'verify' } | ${ [ testData , testDataSig ] } | ${ 0 } | ${ true } }
70+ ${ 'sig' } | ${ 'verify' } | ${ [ testData , testDataWrongSig ] } | ${ 0 } | ${ false } }
71+ ${ 'sig' } | ${ 'sign' } | ${ [ ] } | ${ 1 } | ${ 'sign accepts exactly one argument: data be signed in format of u8 array of bytes' } }
72+ ${ 'sig' } | ${ 'verify' } | ${ [ testData ] } | ${ 1 } | ${ 'verify accepts exactly two arguments: data and signature, both in format of u8 array of bytes' } }
3973 ` . test (
4074 //
4175 '$fnName with $args expected retcode: $retCode and result: $result' ,
@@ -56,7 +90,7 @@ describe('Tests for default handler', () => {
5690 } ;
5791
5892 // act
59- const fn = defaultServices [ req . serviceId ] [ req . fnName ] ;
93+ const fn = builtInServices ( await context ) [ req . serviceId ] [ req . fnName ] ;
6094 const res = await fn ( req ) ;
6195
6296 // assert
@@ -84,7 +118,7 @@ describe('Tests for default handler', () => {
84118 } ;
85119
86120 // act
87- const fn = defaultServices [ req . serviceId ] [ req . fnName ] ;
121+ const fn = builtInServices ( await context ) [ req . serviceId ] [ req . fnName ] ;
88122 const res = await fn ( req ) ;
89123
90124 // assert
@@ -93,4 +127,166 @@ describe('Tests for default handler', () => {
93127 result : 'The JS implementation of Peer does not support identify' ,
94128 } ) ;
95129 } ) ;
130+
131+ it ( 'sig.sign should create the correct signature' , async ( ) => {
132+ // arrange
133+ const ctx = await context ;
134+ const req : CallServiceData = {
135+ serviceId : 'sig' ,
136+ fnName : 'sign' ,
137+ args : [ testData ] ,
138+ tetraplets : [
139+ [
140+ {
141+ function_name : 'get_trust_bytes' ,
142+ json_path : '' ,
143+ peer_pk : '' ,
144+ service_id : 'trust-graph' ,
145+ } ,
146+ ] ,
147+ ] ,
148+ particleContext : {
149+ particleId : 'some' ,
150+ initPeerId : ctx . peerId ,
151+ timestamp : 595951200 ,
152+ ttl : 595961200 ,
153+ signature : 'sig' ,
154+ } ,
155+ } ;
156+
157+ // act
158+ const fn = builtInServices ( ctx ) [ req . serviceId ] [ req . fnName ] ;
159+ const res = await fn ( req ) ;
160+
161+ // assert
162+ expect ( res ) . toMatchObject ( {
163+ retCode : 0 ,
164+ result : testDataSig ,
165+ } ) ;
166+ } ) ;
167+
168+ it ( 'sign-verify call chain should work' , async ( ) => {
169+ const ctx = await context ;
170+ const signReq : CallServiceData = {
171+ serviceId : 'sig' ,
172+ fnName : 'sign' ,
173+ args : [ testData ] ,
174+ tetraplets : [
175+ [
176+ {
177+ function_name : 'get_trust_bytes' ,
178+ json_path : '' ,
179+ peer_pk : '' ,
180+ service_id : 'trust-graph' ,
181+ } ,
182+ ] ,
183+ ] ,
184+ particleContext : {
185+ particleId : 'some' ,
186+ initPeerId : ctx . peerId ,
187+ timestamp : 595951200 ,
188+ ttl : 595961200 ,
189+ signature : 'sig' ,
190+ } ,
191+ } ;
192+
193+ const signFn = builtInServices ( ctx ) [ signReq . serviceId ] [ signReq . fnName ] ;
194+ const signRes = await signFn ( signReq ) ;
195+
196+ const verifyReq : CallServiceData = {
197+ serviceId : 'sig' ,
198+ fnName : 'verify' ,
199+ args : [ testData , signRes . result ] ,
200+ tetraplets : [ ] ,
201+ particleContext : {
202+ particleId : 'some' ,
203+ initPeerId : ctx . peerId ,
204+ timestamp : 595951200 ,
205+ ttl : 595961200 ,
206+ signature : 'sig' ,
207+ } ,
208+ } ;
209+
210+ const verifyFn = builtInServices ( ctx ) [ verifyReq . serviceId ] [ verifyReq . fnName ] ;
211+ const verifyRes = await verifyFn ( verifyReq ) ;
212+
213+ expect ( verifyRes ) . toMatchObject ( {
214+ retCode : 0 ,
215+ result : true ,
216+ } ) ;
217+ } ) ;
218+
219+ it ( 'sig.sign should not allow data from incorrect services' , async ( ) => {
220+ // arrange
221+ const ctx = await context ;
222+ const req : CallServiceData = {
223+ serviceId : 'sig' ,
224+ fnName : 'sign' ,
225+ args : [ testData ] ,
226+ tetraplets : [
227+ [
228+ {
229+ function_name : 'some-other-fn' ,
230+ json_path : '' ,
231+ peer_pk : '' ,
232+ service_id : 'cool-service' ,
233+ } ,
234+ ] ,
235+ ] ,
236+ particleContext : {
237+ particleId : 'some' ,
238+ initPeerId : ctx . peerId ,
239+ timestamp : 595951200 ,
240+ ttl : 595961200 ,
241+ signature : 'sig' ,
242+ } ,
243+ } ;
244+
245+ // act
246+ const fn = builtInServices ( ctx ) [ req . serviceId ] [ req . fnName ] ;
247+ const res = await fn ( req ) ;
248+
249+ // assert
250+ expect ( res ) . toMatchObject ( {
251+ retCode : 1 ,
252+ result : expect . stringContaining ( "Only data from the following services is allowed to be signed:" ) ,
253+ } ) ;
254+ } ) ;
255+
256+ it ( 'sig.sign should not allow particles initiated from other peers' , async ( ) => {
257+ // arrange
258+ const ctx = await context ;
259+ const req : CallServiceData = {
260+ serviceId : 'sig' ,
261+ fnName : 'sign' ,
262+ args : [ testData ] ,
263+ tetraplets : [
264+ [
265+ {
266+ function_name : 'some-other-fn' ,
267+ json_path : '' ,
268+ peer_pk : '' ,
269+ service_id : 'cool-service' ,
270+ } ,
271+ ] ,
272+ ] ,
273+ particleContext : {
274+ particleId : 'some' ,
275+ initPeerId : ( await KeyPair . randomEd25519 ( ) ) . Libp2pPeerId . toB58String ( ) ,
276+ timestamp : 595951200 ,
277+ ttl : 595961200 ,
278+ signature : 'sig' ,
279+ } ,
280+ } ;
281+
282+ // act
283+ const fn = builtInServices ( ctx ) [ req . serviceId ] [ req . fnName ] ;
284+ const res = await fn ( req ) ;
285+
286+ // assert
287+ expect ( res ) . toMatchObject ( {
288+ retCode : 1 ,
289+ result : 'sign is only allowed to be called on the same peer the particle was initiated from' ,
290+ } ) ;
291+ } ) ;
96292} ) ;
0 commit comments