@@ -71,6 +71,105 @@ parser_error_t parser_getNumItems(const parser_context_t *ctx, uint8_t *num_item
71
71
return parser_ok ;
72
72
}
73
73
74
+ // based on Dapper provided code at https://github.com/onflow/flow-go-sdk/blob/96796f0cabc1847d7879a5230ab55fd3cdd41ae8/address.go#L286
75
+
76
+ const uint16_t linearCodeN = 64 ;
77
+ const uint64_t codeword_mainnet = 0 ;
78
+ const uint64_t codeword_testnet = 0x6834ba37b3980209 ;
79
+ const uint64_t codeword_emulatornet = 0x1cb159857af02018 ;
80
+
81
+ const uint32_t parityCheckMatrixColumns [] = {
82
+ 0x00001 , 0x00002 , 0x00004 , 0x00008 ,
83
+ 0x00010 , 0x00020 , 0x00040 , 0x00080 ,
84
+ 0x00100 , 0x00200 , 0x00400 , 0x00800 ,
85
+ 0x01000 , 0x02000 , 0x04000 , 0x08000 ,
86
+ 0x10000 , 0x20000 , 0x40000 , 0x7328d ,
87
+ 0x6689a , 0x6112f , 0x6084b , 0x433fd ,
88
+ 0x42aab , 0x41951 , 0x233ce , 0x22a81 ,
89
+ 0x21948 , 0x1ef60 , 0x1deca , 0x1c639 ,
90
+ 0x1bdd8 , 0x1a535 , 0x194ac , 0x18c46 ,
91
+ 0x1632b , 0x1529b , 0x14a43 , 0x13184 ,
92
+ 0x12942 , 0x118c1 , 0x0f812 , 0x0e027 ,
93
+ 0x0d00e , 0x0c83c , 0x0b01d , 0x0a831 ,
94
+ 0x0982b , 0x07034 , 0x0682a , 0x05819 ,
95
+ 0x03807 , 0x007d2 , 0x00727 , 0x0068e ,
96
+ 0x0067c , 0x0059d , 0x004eb , 0x003b4 ,
97
+ 0x0036a , 0x002d9 , 0x001c7 , 0x0003f ,
98
+ };
99
+
100
+ bool validateChainAddress (uint64_t chainCodeWord , uint64_t address ) {
101
+ uint64_t codeWord = address ^chainCodeWord ;
102
+
103
+ if (codeWord == 0 ) {
104
+ return false;
105
+ }
106
+
107
+ uint64_t parity = 0 ;
108
+ for (uint16_t i = 0 ; i < linearCodeN ; i ++ ) {
109
+ if ((codeWord & 1 ) == 1 ) {
110
+ parity ^= parityCheckMatrixColumns [i ];
111
+ }
112
+ codeWord >>= 1 ;
113
+ }
114
+
115
+ return parity == 0 ;
116
+ }
117
+
118
+ parser_error_t chainIDFromPayer (const flow_payer_t * v , chain_id_e * chainID ) {
119
+ if (v -> ctx .bufferLen != 8 ) {
120
+ return parser_invalid_address ;
121
+ }
122
+
123
+ uint64_t address = 0 ;
124
+ for (uint8_t i = 0 ; i < 8 ; i ++ ) {
125
+ address <<= 8 ;
126
+ address += v -> ctx .buffer [i ];
127
+ }
128
+
129
+ if (validateChainAddress (codeword_mainnet , address )) {
130
+ * chainID = chain_id_mainnet ;
131
+ return parser_ok ;
132
+ }
133
+
134
+ if (validateChainAddress (codeword_testnet , address )) {
135
+ * chainID = chain_id_testnet ;
136
+ return parser_ok ;
137
+ }
138
+
139
+ if (validateChainAddress (codeword_emulatornet , address )) {
140
+ * chainID = chain_id_emulator ;
141
+ return parser_ok ;
142
+ }
143
+
144
+ return parser_unexpected_value ;
145
+ }
146
+
147
+ parser_error_t parser_printChainID (const flow_payer_t * v ,
148
+ char * outVal , uint16_t outValLen ,
149
+ uint8_t pageIdx , uint8_t * pageCount ) {
150
+ MEMZERO (outVal , outValLen );
151
+ chain_id_e chainID ;
152
+ CHECK_PARSER_ERR (chainIDFromPayer (v , & chainID ));
153
+
154
+ * pageCount = 1 ;
155
+ switch (chainID ) {
156
+ case chain_id_mainnet :
157
+ snprintf (outVal , outValLen , "Mainnet" );
158
+ return parser_ok ;
159
+ case chain_id_testnet :
160
+ snprintf (outVal , outValLen , "Testnet" );
161
+ return parser_ok ;
162
+ case chain_id_emulator :
163
+ snprintf (outVal , outValLen , "Emulator" );
164
+ return parser_ok ;
165
+ case chain_id_unknown :
166
+ default :
167
+ return parser_invalid_address ;
168
+ }
169
+
170
+ return parser_invalid_address ;
171
+ }
172
+
74
173
__Z_INLINE parser_error_t parser_printArgument (const flow_argument_list_t * v ,
75
174
uint8_t argIndex , char * expectedType , jsmntype_t jsonType ,
76
175
char * outVal , uint16_t outValLen ,
@@ -264,55 +363,58 @@ parser_error_t parser_getItemTokenTransfer(const parser_context_t *ctx,
264
363
char * outKey , uint16_t outKeyLen ,
265
364
char * outVal , uint16_t outValLen ,
266
365
uint8_t pageIdx , uint8_t * pageCount ) {
267
- if (displayIdx == 0 ) {
268
- snprintf (outKey , outKeyLen , "Type" );
269
- snprintf (outVal , outValLen , "Token Transfer" );
270
- return parser_ok ;
271
- }
272
- displayIdx -- ;
366
+ * pageCount = 1 ;
273
367
274
368
switch (displayIdx ) {
275
369
case 0 :
370
+ snprintf (outKey , outKeyLen , "Type" );
371
+ snprintf (outVal , outValLen , "Token Transfer" );
372
+ return parser_ok ;
373
+ case 1 :
374
+ snprintf (outKey , outKeyLen , "ChainID" );
375
+ return parser_printChainID (& parser_tx_obj .payer ,
376
+ outVal , outValLen , pageIdx , pageCount );
377
+ case 2 :
276
378
snprintf (outKey , outKeyLen , "Amount" );
277
- return parser_printArgument (& parser_tx_obj .arguments , displayIdx ,
379
+ return parser_printArgument (& parser_tx_obj .arguments , 0 ,
278
380
"UFix64" , JSMN_STRING ,
279
381
outVal , outValLen , pageIdx , pageCount );
280
- case 1 :
382
+ case 3 :
281
383
snprintf (outKey , outKeyLen , "Destination" );
282
- return parser_printArgument (& parser_tx_obj .arguments , displayIdx ,
384
+ return parser_printArgument (& parser_tx_obj .arguments , 1 ,
283
385
"Address" , JSMN_STRING ,
284
386
outVal , outValLen , pageIdx , pageCount );
285
- case 2 :
387
+ case 4 :
286
388
snprintf (outKey , outKeyLen , "Ref Block" );
287
389
return parser_printBlockId (& parser_tx_obj .referenceBlockId , outVal , outValLen , pageIdx , pageCount );
288
- case 3 :
390
+ case 5 :
289
391
snprintf (outKey , outKeyLen , "Gas Limit" );
290
392
return parser_printGasLimit (& parser_tx_obj .gasLimit , outVal , outValLen , pageIdx , pageCount );
291
- case 4 :
393
+ case 6 :
292
394
snprintf (outKey , outKeyLen , "Prop Key Addr" );
293
395
return parser_printPropKeyAddr (& parser_tx_obj .proposalKeyAddress , outVal , outValLen , pageIdx , pageCount );
294
- case 5 :
396
+ case 7 :
295
397
snprintf (outKey , outKeyLen , "Prop Key Id" );
296
398
return parser_printPropKeyId (& parser_tx_obj .proposalKeyId , outVal , outValLen , pageIdx , pageCount );
297
- case 6 :
399
+ case 8 :
298
400
snprintf (outKey , outKeyLen , "Prop Key Seq Num" );
299
401
return parser_printPropSeqNum (& parser_tx_obj .proposalKeySequenceNumber , outVal , outValLen , pageIdx ,
300
402
pageCount );
301
- case 7 :
403
+ case 9 :
302
404
snprintf (outKey , outKeyLen , "Payer" );
303
405
return parser_printPayer (& parser_tx_obj .payer , outVal , outValLen , pageIdx , pageCount );
304
406
default :
305
407
break ;
306
408
}
307
- displayIdx -= 8 ;
409
+ displayIdx -= 10 ;
308
410
309
411
if (displayIdx < parser_tx_obj .authorizers .authorizer_count ) {
310
412
snprintf (outKey , outKeyLen , "Authorizer %d" , displayIdx + 1 );
311
413
return parser_printAuthorizer (& parser_tx_obj .authorizers .authorizer [displayIdx ], outVal , outValLen , pageIdx ,
312
414
pageCount );
313
415
}
314
416
315
- return parser_ok ;
417
+ return parser_display_idx_out_of_range ;
316
418
}
317
419
318
420
parser_error_t parser_getItemCreateAccount (const parser_context_t * ctx ,
@@ -321,13 +423,20 @@ parser_error_t parser_getItemCreateAccount(const parser_context_t *ctx,
321
423
char * outVal , uint16_t outValLen ,
322
424
uint8_t pageIdx , uint8_t * pageCount ) {
323
425
zemu_log_stack ("parser_getItemCreateAccount" );
426
+ * pageCount = 1 ;
324
427
325
428
if (displayIdx == 0 ) {
326
429
snprintf (outKey , outKeyLen , "Type" );
327
430
snprintf (outVal , outValLen , "Create Account" );
328
431
return parser_ok ;
329
432
}
330
433
displayIdx -- ;
434
+ if (displayIdx == 0 ) {
435
+ snprintf (outKey , outKeyLen , "ChainID" );
436
+ return parser_printChainID (& parser_tx_obj .payer ,
437
+ outVal , outValLen , pageIdx , pageCount );
438
+ }
439
+ displayIdx -- ;
331
440
332
441
const uint8_t pkCount = _countArgumentItems (& parser_tx_obj .arguments , 0 );
333
442
if (displayIdx < pkCount ) {
@@ -372,58 +481,63 @@ parser_error_t parser_getItemCreateAccount(const parser_context_t *ctx,
372
481
pageCount );
373
482
}
374
483
375
- return parser_ok ;
484
+ return parser_display_idx_out_of_range ;
376
485
}
377
486
378
487
parser_error_t parser_getItemAddNewKey (const parser_context_t * ctx ,
379
488
uint16_t displayIdx ,
380
489
char * outKey , uint16_t outKeyLen ,
381
490
char * outVal , uint16_t outValLen ,
382
491
uint8_t pageIdx , uint8_t * pageCount ) {
492
+ * pageCount = 1 ;
383
493
switch (displayIdx ) {
384
494
case 0 :
385
495
snprintf (outKey , outKeyLen , "Type" );
386
496
snprintf (outVal , outValLen , "Add New Key" );
387
497
return parser_ok ;
388
- case 1 : {
498
+ case 1 :
499
+ snprintf (outKey , outKeyLen , "ChainID" );
500
+ return parser_printChainID (& parser_tx_obj .payer ,
501
+ outVal , outValLen , pageIdx , pageCount );
502
+ case 2 : {
389
503
CHECK_PARSER_ERR (
390
504
parser_printArgumentPublicKey (
391
505
& parser_tx_obj .arguments .argCtx [0 ], outVal , outValLen ,
392
506
pageIdx , pageCount ))
393
507
snprintf (outKey , outKeyLen , "Pub key" );
394
508
return parser_ok ;
395
509
}
396
- case 2 :
510
+ case 3 :
397
511
snprintf (outKey , outKeyLen , "Ref Block" );
398
512
return parser_printBlockId (& parser_tx_obj .referenceBlockId , outVal , outValLen , pageIdx , pageCount );
399
- case 3 :
513
+ case 4 :
400
514
snprintf (outKey , outKeyLen , "Gas Limit" );
401
515
return parser_printGasLimit (& parser_tx_obj .gasLimit , outVal , outValLen , pageIdx , pageCount );
402
- case 4 :
516
+ case 5 :
403
517
snprintf (outKey , outKeyLen , "Prop Key Addr" );
404
518
return parser_printPropKeyAddr (& parser_tx_obj .proposalKeyAddress , outVal , outValLen , pageIdx , pageCount );
405
- case 5 :
519
+ case 6 :
406
520
snprintf (outKey , outKeyLen , "Prop Key Id" );
407
521
return parser_printPropKeyId (& parser_tx_obj .proposalKeyId , outVal , outValLen , pageIdx , pageCount );
408
- case 6 :
522
+ case 7 :
409
523
snprintf (outKey , outKeyLen , "Prop Key Seq Num" );
410
524
return parser_printPropSeqNum (& parser_tx_obj .proposalKeySequenceNumber , outVal , outValLen , pageIdx ,
411
525
pageCount );
412
- case 7 :
526
+ case 8 :
413
527
snprintf (outKey , outKeyLen , "Payer" );
414
528
return parser_printPayer (& parser_tx_obj .payer , outVal , outValLen , pageIdx , pageCount );
415
529
default :
416
530
break ;
417
531
}
418
- displayIdx -= 8 ;
532
+ displayIdx -= 9 ;
419
533
420
534
if (displayIdx < parser_tx_obj .authorizers .authorizer_count ) {
421
535
snprintf (outKey , outKeyLen , "Authorizer %d" , displayIdx + 1 );
422
536
return parser_printAuthorizer (& parser_tx_obj .authorizers .authorizer [displayIdx ], outVal , outValLen , pageIdx ,
423
537
pageCount );
424
538
}
425
539
426
- return parser_ok ;
540
+ return parser_display_idx_out_of_range ;
427
541
}
428
542
429
543
parser_error_t parser_getItem (const parser_context_t * ctx ,
0 commit comments