cardano-serialization-lib 15.0.3

(De)serialization functions for the Cardano blockchain along with related utility functions
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
use crate::*;
use hex::*;
use crate::tests::fakes::{fake_byron_address, fake_key_hash, fake_script_hash};

#[test]
pub fn plutus_constr_data() {
    let constr_0 = PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
        &BigNum(0),
        &PlutusList::new(),
    ));
    let constr_0_hash = hex::encode(hash_plutus_data(&constr_0).to_bytes());
    assert_eq!(
        constr_0_hash,
        "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"
    );
    // let constr_0_roundtrip = PlutusData::from_bytes(constr_0.to_bytes()).unwrap();
    // TODO: do we want semantic equality or bytewise equality?
    // assert_eq!(constr_0, constr_0_roundtrip);
    // let constr_1854 = PlutusData::new_constr_plutus_data(
    //     &ConstrPlutusData::new(&BigNum(1854), &PlutusList::new())
    // );
    // let constr_1854_roundtrip = PlutusData::from_bytes(constr_1854.to_bytes()).unwrap();
    // assert_eq!(constr_1854, constr_1854_roundtrip);
}

#[test]
pub fn plutus_list_serialization_cli_compatibility() {
    // mimic cardano-cli array encoding, see https://github.com/Emurgo/cardano-serialization-lib/issues/227
    let datum_cli = "d8799f4100d8799fd8799fd8799f581cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8799fd8799fd8799f581cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd87a80ff1a002625a0d8799fd879801a000f4240d87a80ffff";
    let datum = PlutusData::from_bytes(Vec::from_hex(datum_cli).unwrap()).unwrap();
    assert_eq!(datum_cli, hex::encode(datum.to_bytes()));

    // encode empty arrays as fixed
    assert_eq!("80", hex::encode(PlutusList::new().to_bytes()));

    // encode arrays as indefinite length array
    let mut list = PlutusList::new();
    list.add(&PlutusData::new_integer(&BigInt::from_str("1").unwrap()));
    assert_eq!("9f01ff", hex::encode(list.to_bytes()));

    // witness_set should have fixed length array
    let mut witness_set = TransactionWitnessSet::new();
    witness_set.set_plutus_data(&list);
    assert_eq!("a104d901029f01ff", hex::encode(witness_set.to_bytes()));

    list = PlutusList::new();
    list.add(&datum);
    witness_set.set_plutus_data(&list);
    assert_eq!(
        format!("a104d901029f{}ff", datum_cli),
        hex::encode(witness_set.to_bytes())
    );
}

#[test]
pub fn plutus_datums_respect_deserialized_encoding() {
    let orig_bytes = Vec::from_hex(
        "81d8799f581ce1cbb80db89e292269aeb93ec15eb963dda5176b66949fe1c2a6a38da140a1401864ff",
    )
    .unwrap();
    let datums = PlutusList::from_bytes(orig_bytes.clone()).unwrap();
    let new_bytes = datums.to_bytes();
    assert_eq!(orig_bytes, new_bytes);
}

#[test]
pub fn plutus_datum_from_json_basic() {
    let json = "{
            \"5\": \"some utf8 string\",
            \"0xDEADBEEF\": [
                {\"reg string\": {}},
                -9
            ]
        }";

    let datum = encode_json_str_to_plutus_datum(json, PlutusDatumSchema::BasicConversions).unwrap();

    let map = datum.as_map().unwrap();
    let map_5 = map
        .get(&PlutusData::new_integer(&BigInt::from_str("5").unwrap()))
        .unwrap();
    let utf8_bytes = "some utf8 string".as_bytes();
    assert_eq!(map_5.get(0).unwrap().as_bytes().unwrap(), utf8_bytes);
    let map_deadbeef: PlutusList = map
        .get(&PlutusData::new_bytes(vec![222, 173, 190, 239]))
        .expect("DEADBEEF key not found")
        .get(0)
        .unwrap()
        .as_list()
        .expect("must be a map");
    assert_eq!(map_deadbeef.len(), 2);
    let inner_map = map_deadbeef.get(0).as_map().unwrap();
    assert_eq!(inner_map.len(), 1);
    let reg_string = inner_map
        .get(&PlutusData::new_bytes("reg string".as_bytes().to_vec()))
        .unwrap()
        .get(0)
        .unwrap();
    assert_eq!(reg_string.as_map().expect("reg string: {}").len(), 0);
    assert_eq!(
        map_deadbeef.get(1).as_integer(),
        BigInt::from_str("-9").ok()
    );

    // test round-trip via generated JSON
    let json2 =
        decode_plutus_datum_to_json_str(&datum, PlutusDatumSchema::BasicConversions).unwrap();
    let datum2 =
        encode_json_str_to_plutus_datum(&json2, PlutusDatumSchema::BasicConversions).unwrap();
    assert_eq!(datum, datum2);
}

#[test]
pub fn plutus_datum_from_json_detailed_duplicated_keys() {
    let json = "{\"list\": [
            {\"map\": [
                {\"k\": {\"bytes\": \"DEADBEEF\"}, \"v\": {\"int\": 42}},
                {\"k\": {\"bytes\": \"DEADBEEF\"}, \"v\": {\"int\": 43}},
                {\"k\": {\"map\" : [
                    {\"k\": {\"int\": 9}, \"v\": {\"int\": -5}}
                ]}, \"v\": {\"list\": []}}
            ]}
        ]}";
    let datum = encode_json_str_to_plutus_datum(json, PlutusDatumSchema::DetailedSchema).unwrap();

    let list = datum.as_list().unwrap();
    assert_eq!(1, list.len());
    // map
    let map = list.get(0).as_map().unwrap();
    assert_eq!(map.len(), 2);
    let map_deadbeef = map
        .get(&PlutusData::new_bytes(vec![222, 173, 190, 239]))
        .unwrap();
    assert_eq!(map_deadbeef.len(), 2);
    assert_eq!(map_deadbeef.get(0).unwrap().as_integer(), BigInt::from_str("42").ok());
    assert_eq!(map_deadbeef.get(1).unwrap().as_integer(), BigInt::from_str("43").ok());
    let mut long_key = PlutusMap::new();
    long_key.add_value(
        &PlutusData::new_integer(&BigInt::from_str("9").unwrap()),
        &PlutusData::new_integer(&BigInt::from_str("-5").unwrap()),
    );
    let map_9_to_5 = map
        .get(&PlutusData::new_map(&long_key))
        .unwrap()
        .get(0)
        .unwrap()
        .as_list()
        .unwrap();
    assert_eq!(map_9_to_5.len(), 0);

    // test round-trip via generated JSON
    let json2 = decode_plutus_datum_to_json_str(&datum, PlutusDatumSchema::DetailedSchema).unwrap();
    let datum2 =
        encode_json_str_to_plutus_datum(&json2, PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, datum2);
}

#[test]
pub fn plutus_datum_from_json_detailed() {
    let json = "{\"list\": [
            {\"map\": [
                {\"k\": {\"bytes\": \"DEADBEEF\"}, \"v\": {\"int\": 42}},
                {\"k\": {\"map\" : [
                    {\"k\": {\"int\": 9}, \"v\": {\"int\": -5}}
                ]}, \"v\": {\"list\": []}}
            ]},
            {\"bytes\": \"CAFED00D\"},
            {\"constructor\": 0, \"fields\": [
                {\"map\": []},
                {\"int\": 23}
            ]}
        ]}";
    let datum = encode_json_str_to_plutus_datum(json, PlutusDatumSchema::DetailedSchema).unwrap();

    let list = datum.as_list().unwrap();
    assert_eq!(3, list.len());
    // map
    let map = list.get(0).as_map().unwrap();
    assert_eq!(map.len(), 2);
    let map_deadbeef = map
        .get(&PlutusData::new_bytes(vec![222, 173, 190, 239]))
        .unwrap();
    assert_eq!(map_deadbeef.get(0).unwrap().as_integer(), BigInt::from_str("42").ok());
    let mut long_key = PlutusMap::new();
    long_key.add_value(
        &PlutusData::new_integer(&BigInt::from_str("9").unwrap()),
        &PlutusData::new_integer(&BigInt::from_str("-5").unwrap()),
    );
    let map_9_to_5 = map
        .get(&PlutusData::new_map(&long_key))
        .unwrap()
        .get(0)
        .unwrap()
        .as_list()
        .unwrap();
    assert_eq!(map_9_to_5.len(), 0);
    // bytes
    let bytes = list.get(1).as_bytes().unwrap();
    assert_eq!(bytes, [202, 254, 208, 13]);
    // constr data
    let constr = list.get(2).as_constr_plutus_data().unwrap();
    assert_eq!(BigNum(0), constr.alternative());
    let fields = constr.data();
    assert_eq!(fields.len(), 2);
    let field0 = fields.get(0).as_map().unwrap();
    assert_eq!(field0.len(), 0);
    let field1 = fields.get(1);
    assert_eq!(field1.as_integer(), BigInt::from_str("23").ok());

    // test round-trip via generated JSON
    let json2 = decode_plutus_datum_to_json_str(&datum, PlutusDatumSchema::DetailedSchema).unwrap();
    let datum2 =
        encode_json_str_to_plutus_datum(&json2, PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, datum2);
}

#[test]
pub fn test_cost_model() {
    let arr = vec![
        197209, 0, 1, 1, 396231, 621, 0, 1, 150000, 1000, 0, 1, 150000, 32, 2477736, 29175, 4,
        29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 29773, 100, 100, 100, 29773,
        100, 150000, 32, 150000, 32, 150000, 32, 150000, 1000, 0, 1, 150000, 32, 150000, 1000, 0,
        8, 148000, 425507, 118, 0, 1, 1, 150000, 1000, 0, 8, 150000, 112536, 247, 1, 150000, 10000,
        1, 136542, 1326, 1, 1000, 150000, 1000, 1, 150000, 32, 150000, 32, 150000, 32, 1, 1,
        150000, 1, 150000, 4, 103599, 248, 1, 103599, 248, 1, 145276, 1366, 1, 179690, 497, 1,
        150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 148000, 425507,
        118, 0, 1, 1, 61516, 11218, 0, 1, 150000, 32, 148000, 425507, 118, 0, 1, 1, 148000, 425507,
        118, 0, 1, 1, 2477736, 29175, 4, 0, 82363, 4, 150000, 5000, 0, 1, 150000, 32, 197209, 0, 1,
        1, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32, 150000, 32,
        3345831, 1, 1,
    ];
    let cm = arr
        .iter()
        .fold((CostModel::new(), 0), |(mut cm, i), x| {
            cm.set(i, &Int::new_i32(x.clone())).unwrap();
            (cm, i + 1)
        })
        .0;
    let mut cms = Costmdls::new();
    cms.insert(&Language::new_plutus_v1(), &cm);
    assert_eq!(
            hex::encode(cms.language_views_encoding()),
            "a141005901d59f1a000302590001011a00060bc719026d00011a000249f01903e800011a000249f018201a0025cea81971f70419744d186419744d186419744d186419744d186419744d186419744d18641864186419744d18641a000249f018201a000249f018201a000249f018201a000249f01903e800011a000249f018201a000249f01903e800081a000242201a00067e2318760001011a000249f01903e800081a000249f01a0001b79818f7011a000249f0192710011a0002155e19052e011903e81a000249f01903e8011a000249f018201a000249f018201a000249f0182001011a000249f0011a000249f0041a000194af18f8011a000194af18f8011a0002377c190556011a0002bdea1901f1011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000242201a00067e23187600010119f04c192bd200011a000249f018201a000242201a00067e2318760001011a000242201a00067e2318760001011a0025cea81971f704001a000141bb041a000249f019138800011a000249f018201a000302590001011a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a000249f018201a00330da70101ff"
        );
}

#[test]
fn test_plutus_script_hash() {
    let hash = EnterpriseAddress::from_address(
        &Address::from_bech32("addr1w896t6qnpsjs32xhw8jl3kw34pqz69kgd72l8hqw83w0k3qahx2sv")
            .unwrap(),
    )
    .unwrap()
    .payment_cred()
    .to_scripthash()
    .unwrap();
    let script = PlutusScript::from_bytes(
            hex::decode("590e6f590e6c0100003323332223322333222332232332233223232333222323332223233333333222222223233322232333322223232332232323332223232332233223232333332222233223322332233223322332222323232232232325335303233300a3333573466e1cd55cea8042400046664446660a40060040026eb4d5d0a8041bae35742a00e66a05046666ae68cdc39aab9d37540029000102b11931a982599ab9c04f04c04a049357426ae89401c8c98d4c124cd5ce0268250240239999ab9a3370ea0089001102b11999ab9a3370ea00a9000102c11931a982519ab9c04e04b0490480473333573466e1cd55cea8012400046601a64646464646464646464646666ae68cdc39aab9d500a480008cccccccccc06ccd40a48c8c8cccd5cd19b8735573aa0049000119810981c9aba15002302e357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854028cd40a40a8d5d0a804999aa8183ae502f35742a010666aa060eb940bcd5d0a80399a8148211aba15006335029335505304b75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8119919191999ab9a3370e6aae7540092000233502b33504175a6ae854008c118d5d09aba25002232635305d3357380c20bc0b80b626aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a05266a082eb4d5d0a80118231aba135744a004464c6a60ba66ae7018417817016c4d55cf280089baa001357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854010cd40a5d71aba15003335029335505375c40026ae854008c0e0d5d09aba2500223263530553357380b20ac0a80a626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d4005200623020303a357426aae79400c8cccd5cd19b875002480108c07cc110d5d09aab9e500423333573466e1d400d20022301f302f357426aae7940148cccd5cd19b875004480008c088dd71aba135573ca00c464c6a60a066ae7015014413c13813413012c4d55cea80089baa001357426ae8940088c98d4c124cd5ce026825024023882489931a982419ab9c4910350543500049047135573ca00226ea80044d55ce9baa001135744a00226aae7940044dd50009109198008018011000911111111109199999999980080580500480400380300280200180110009109198008018011000891091980080180109000891091980080180109000891091980080180109000909111180200290911118018029091111801002909111180080290008919118011bac0013200135503c2233335573e0024a01c466a01a60086ae84008c00cd5d100101811919191999ab9a3370e6aae75400d200023330073232323333573466e1cd55cea8012400046601a605c6ae854008cd404c0a8d5d09aba25002232635303433573807006a06606426aae7940044dd50009aba150033335500b75ca0146ae854008cd403dd71aba135744a004464c6a606066ae700d00c40bc0b84d5d1280089aab9e5001137540024442466600200800600440024424660020060044002266aa002eb9d6889119118011bab00132001355036223233335573e0044a012466a01066aa05c600c6aae754008c014d55cf280118021aba200302b1357420022244004244244660020080062400224464646666ae68cdc3a800a400046a05e600a6ae84d55cf280191999ab9a3370ea00490011281791931a981399ab9c02b028026025024135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011980318039aba15002375a6ae84d5d1280111931a981219ab9c028025023022135573ca00226ea80048848cc00400c00880048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4c080cd5ce01201080f80f09baa00112232323333573466e1d400520042500723333573466e1d4009200223500a3006357426aae7940108cccd5cd19b87500348000940288c98d4c08ccd5ce01381201101081000f89aab9d50011375400224244460060082244400422444002240024646666ae68cdc3a800a4004400c46666ae68cdc3a80124000400c464c6a603666ae7007c0700680640604d55ce9baa0011220021220012001232323232323333573466e1d4005200c200b23333573466e1d4009200a200d23333573466e1d400d200823300b375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c46601a6eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc048c050d5d0a8049bae357426ae8940248cccd5cd19b875006480088c050c054d5d09aab9e500b23333573466e1d401d2000230133016357426aae7940308c98d4c080cd5ce01201080f80f00e80e00d80d00c80c09aab9d5004135573ca00626aae7940084d55cf280089baa00121222222230070082212222222330060090082122222223005008122222220041222222200322122222223300200900822122222223300100900820012323232323333573466e1d400520022333008375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea00490001180518059aba135573ca00c464c6a602266ae7005404804003c0384d55cea80189aba25001135573ca00226ea80048488c00800c888488ccc00401401000c80048c8c8cccd5cd19b875001480088c018dd71aba135573ca00646666ae68cdc3a80124000460106eb8d5d09aab9e5004232635300b33573801e01801401201026aae7540044dd5000909118010019091180080190008891119191999ab9a3370e6aae75400920002335500b300635742a004600a6ae84d5d1280111931a980419ab9c00c009007006135573ca00226ea800526120012001112212330010030021120014910350543100222123330010040030022001121223002003112200112001120012001122002122001200111232300100122330033002002001332323233322233322233223332223322332233322233223322332233223233322232323322323232323333222232332232323222323222325335301a5335301a333573466e1cc8cccd54c05048004c8cd406488ccd406400c004008d4058004cd4060888c00cc008004800488cdc0000a40040029000199aa98068900091299a980e299a9a81a1a98169a98131a9812001110009110019119a98188011281c11a81c8009080f880e899a8148010008800a8141a981028009111111111005240040380362038266ae712413c53686f756c642062652065786163746c79206f6e652073637269707420696e70757420746f2061766f696420646f75626c65207361742069737375650001b15335303500315335301a5335301a333573466e20ccc064ccd54c03448005402540a0cc020d4c0c00188880094004074074cdc09a9818003111001a80200d80e080e099ab9c49010f73656c6c6572206e6f7420706169640001b15335301a333573466e20ccc064cc88ccd54c03c48005402d40a8cc028004009400401c074075401006c07040704cd5ce24810d66656573206e6f7420706169640001b101b15335301a3322353022002222222222253353503e33355301f1200133502322533535040002210031001503f253353027333573466e3c0300040a40a04d41040045410000c840a4409d4004d4c0c001888800840704cd5ce2491c4f6e6c792073656c6c65722063616e2063616e63656c206f666665720001b101b135301d00122002153353016333573466e2540040d406005c40d4540044cdc199b8235302b001222003480c920d00f2235301a0012222222222333553011120012235302a002222353034003223353038002253353026333573466e3c0500040a009c4cd40cc01401c401c801d40b0024488cd54c02c480048d4d5408c00488cd54098008cd54c038480048d4d5409800488cd540a4008ccd4d540340048cc0e12000001223303900200123303800148000004cd54c02c480048d4d5408c00488cd54098008ccd4d540280048cd54c03c480048d4d5409c00488cd540a8008d5404400400488ccd5540200580080048cd54c03c480048d4d5409c00488cd540a8008d5403c004004ccd55400c044008004444888ccd54c018480054080cd54c02c480048d4d5408c00488cd54098008d54034004ccd54c0184800488d4d54090008894cd4c05cccd54c04048004c8cd405488ccd4d402c00c88008008004d4d402400488004cd4024894cd4c064008406c40040608d4d5409c00488cc028008014018400c4cd409001000d4084004cd54c02c480048d4d5408c00488c8cd5409c00cc004014c8004d540d8894cd4d40900044d5403400c884d4d540a4008894cd4c070cc0300080204cd5404801c0044c01800c00848848cc00400c00848004c8004d540b488448894cd4d40780044008884cc014008ccd54c01c480040140100044484888c00c01044884888cc0080140104484888c004010448004c8004d540a08844894cd4d406000454068884cd406cc010008cd54c01848004010004c8004d5409c88448894cd4d40600044d401800c884ccd4024014c010008ccd54c01c4800401401000448d4d400c0048800448d4d40080048800848848cc00400c0084800488ccd5cd19b8f002001006005222323230010053200135502522335350130014800088d4d54060008894cd4c02cccd5cd19b8f00200900d00c13007001130060033200135502422335350120014800088d4d5405c008894cd4c028ccd5cd19b8f00200700c00b10011300600312200212200120014881002212330010030022001222222222212333333333300100b00a009008007006005004003002200122123300100300220012221233300100400300220011122002122122330010040031200111221233001003002112001221233001003002200121223002003212230010032001222123330010040030022001121223002003112200112001122002122001200122337000040029040497a0088919180080091198019801001000a4411c28f07a93d7715db0bdc1766c8bd5b116602b105c02c54fc3bcd0d4680001").unwrap().clone(),
        ).unwrap();
    assert_eq!(script.hash(), hash);
}

#[test]
fn test_plutus_script_from_hex_with_version() {
    let script_v1 = PlutusScript::from_hex_with_version(
            "590e6f590e6c0100003323332223322333222332232332233223232333222323332223233333333222222223233322232333322223232332232323332223232332233223232333332222233223322332233223322332222323232232232325335303233300a3333573466e1cd55cea8042400046664446660a40060040026eb4d5d0a8041bae35742a00e66a05046666ae68cdc39aab9d37540029000102b11931a982599ab9c04f04c04a049357426ae89401c8c98d4c124cd5ce0268250240239999ab9a3370ea0089001102b11999ab9a3370ea00a9000102c11931a982519ab9c04e04b0490480473333573466e1cd55cea8012400046601a64646464646464646464646666ae68cdc39aab9d500a480008cccccccccc06ccd40a48c8c8cccd5cd19b8735573aa0049000119810981c9aba15002302e357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854028cd40a40a8d5d0a804999aa8183ae502f35742a010666aa060eb940bcd5d0a80399a8148211aba15006335029335505304b75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8119919191999ab9a3370e6aae7540092000233502b33504175a6ae854008c118d5d09aba25002232635305d3357380c20bc0b80b626aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a05266a082eb4d5d0a80118231aba135744a004464c6a60ba66ae7018417817016c4d55cf280089baa001357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854010cd40a5d71aba15003335029335505375c40026ae854008c0e0d5d09aba2500223263530553357380b20ac0a80a626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d4005200623020303a357426aae79400c8cccd5cd19b875002480108c07cc110d5d09aab9e500423333573466e1d400d20022301f302f357426aae7940148cccd5cd19b875004480008c088dd71aba135573ca00c464c6a60a066ae7015014413c13813413012c4d55cea80089baa001357426ae8940088c98d4c124cd5ce026825024023882489931a982419ab9c4910350543500049047135573ca00226ea80044d55ce9baa001135744a00226aae7940044dd50009109198008018011000911111111109199999999980080580500480400380300280200180110009109198008018011000891091980080180109000891091980080180109000891091980080180109000909111180200290911118018029091111801002909111180080290008919118011bac0013200135503c2233335573e0024a01c466a01a60086ae84008c00cd5d100101811919191999ab9a3370e6aae75400d200023330073232323333573466e1cd55cea8012400046601a605c6ae854008cd404c0a8d5d09aba25002232635303433573807006a06606426aae7940044dd50009aba150033335500b75ca0146ae854008cd403dd71aba135744a004464c6a606066ae700d00c40bc0b84d5d1280089aab9e5001137540024442466600200800600440024424660020060044002266aa002eb9d6889119118011bab00132001355036223233335573e0044a012466a01066aa05c600c6aae754008c014d55cf280118021aba200302b1357420022244004244244660020080062400224464646666ae68cdc3a800a400046a05e600a6ae84d55cf280191999ab9a3370ea00490011281791931a981399ab9c02b028026025024135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011980318039aba15002375a6ae84d5d1280111931a981219ab9c028025023022135573ca00226ea80048848cc00400c00880048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4c080cd5ce01201080f80f09baa00112232323333573466e1d400520042500723333573466e1d4009200223500a3006357426aae7940108cccd5cd19b87500348000940288c98d4c08ccd5ce01381201101081000f89aab9d50011375400224244460060082244400422444002240024646666ae68cdc3a800a4004400c46666ae68cdc3a80124000400c464c6a603666ae7007c0700680640604d55ce9baa0011220021220012001232323232323333573466e1d4005200c200b23333573466e1d4009200a200d23333573466e1d400d200823300b375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c46601a6eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc048c050d5d0a8049bae357426ae8940248cccd5cd19b875006480088c050c054d5d09aab9e500b23333573466e1d401d2000230133016357426aae7940308c98d4c080cd5ce01201080f80f00e80e00d80d00c80c09aab9d5004135573ca00626aae7940084d55cf280089baa00121222222230070082212222222330060090082122222223005008122222220041222222200322122222223300200900822122222223300100900820012323232323333573466e1d400520022333008375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea00490001180518059aba135573ca00c464c6a602266ae7005404804003c0384d55cea80189aba25001135573ca00226ea80048488c00800c888488ccc00401401000c80048c8c8cccd5cd19b875001480088c018dd71aba135573ca00646666ae68cdc3a80124000460106eb8d5d09aab9e5004232635300b33573801e01801401201026aae7540044dd5000909118010019091180080190008891119191999ab9a3370e6aae75400920002335500b300635742a004600a6ae84d5d1280111931a980419ab9c00c009007006135573ca00226ea800526120012001112212330010030021120014910350543100222123330010040030022001121223002003112200112001120012001122002122001200111232300100122330033002002001332323233322233322233223332223322332233322233223322332233223233322232323322323232323333222232332232323222323222325335301a5335301a333573466e1cc8cccd54c05048004c8cd406488ccd406400c004008d4058004cd4060888c00cc008004800488cdc0000a40040029000199aa98068900091299a980e299a9a81a1a98169a98131a9812001110009110019119a98188011281c11a81c8009080f880e899a8148010008800a8141a981028009111111111005240040380362038266ae712413c53686f756c642062652065786163746c79206f6e652073637269707420696e70757420746f2061766f696420646f75626c65207361742069737375650001b15335303500315335301a5335301a333573466e20ccc064ccd54c03448005402540a0cc020d4c0c00188880094004074074cdc09a9818003111001a80200d80e080e099ab9c49010f73656c6c6572206e6f7420706169640001b15335301a333573466e20ccc064cc88ccd54c03c48005402d40a8cc028004009400401c074075401006c07040704cd5ce24810d66656573206e6f7420706169640001b101b15335301a3322353022002222222222253353503e33355301f1200133502322533535040002210031001503f253353027333573466e3c0300040a40a04d41040045410000c840a4409d4004d4c0c001888800840704cd5ce2491c4f6e6c792073656c6c65722063616e2063616e63656c206f666665720001b101b135301d00122002153353016333573466e2540040d406005c40d4540044cdc199b8235302b001222003480c920d00f2235301a0012222222222333553011120012235302a002222353034003223353038002253353026333573466e3c0500040a009c4cd40cc01401c401c801d40b0024488cd54c02c480048d4d5408c00488cd54098008cd54c038480048d4d5409800488cd540a4008ccd4d540340048cc0e12000001223303900200123303800148000004cd54c02c480048d4d5408c00488cd54098008ccd4d540280048cd54c03c480048d4d5409c00488cd540a8008d5404400400488ccd5540200580080048cd54c03c480048d4d5409c00488cd540a8008d5403c004004ccd55400c044008004444888ccd54c018480054080cd54c02c480048d4d5408c00488cd54098008d54034004ccd54c0184800488d4d54090008894cd4c05cccd54c04048004c8cd405488ccd4d402c00c88008008004d4d402400488004cd4024894cd4c064008406c40040608d4d5409c00488cc028008014018400c4cd409001000d4084004cd54c02c480048d4d5408c00488c8cd5409c00cc004014c8004d540d8894cd4d40900044d5403400c884d4d540a4008894cd4c070cc0300080204cd5404801c0044c01800c00848848cc00400c00848004c8004d540b488448894cd4d40780044008884cc014008ccd54c01c480040140100044484888c00c01044884888cc0080140104484888c004010448004c8004d540a08844894cd4d406000454068884cd406cc010008cd54c01848004010004c8004d5409c88448894cd4d40600044d401800c884ccd4024014c010008ccd54c01c4800401401000448d4d400c0048800448d4d40080048800848848cc00400c0084800488ccd5cd19b8f002001006005222323230010053200135502522335350130014800088d4d54060008894cd4c02cccd5cd19b8f00200900d00c13007001130060033200135502422335350120014800088d4d5405c008894cd4c028ccd5cd19b8f00200700c00b10011300600312200212200120014881002212330010030022001222222222212333333333300100b00a009008007006005004003002200122123300100300220012221233300100400300220011122002122122330010040031200111221233001003002112001221233001003002200121223002003212230010032001222123330010040030022001121223002003112200112001122002122001200122337000040029040497a0088919180080091198019801001000a4411c28f07a93d7715db0bdc1766c8bd5b116602b105c02c54fc3bcd0d4680001",
            &Language::new_plutus_v1()
        ).unwrap();
    assert_eq!(script_v1.language, Language::new_plutus_v1().0);

    let script_v2 = PlutusScript::from_hex_with_version(
            "590e6f590e6c0100003323332223322333222332232332233223232333222323332223233333333222222223233322232333322223232332232323332223232332233223232333332222233223322332233223322332222323232232232325335303233300a3333573466e1cd55cea8042400046664446660a40060040026eb4d5d0a8041bae35742a00e66a05046666ae68cdc39aab9d37540029000102b11931a982599ab9c04f04c04a049357426ae89401c8c98d4c124cd5ce0268250240239999ab9a3370ea0089001102b11999ab9a3370ea00a9000102c11931a982519ab9c04e04b0490480473333573466e1cd55cea8012400046601a64646464646464646464646666ae68cdc39aab9d500a480008cccccccccc06ccd40a48c8c8cccd5cd19b8735573aa0049000119810981c9aba15002302e357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854028cd40a40a8d5d0a804999aa8183ae502f35742a010666aa060eb940bcd5d0a80399a8148211aba15006335029335505304b75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8119919191999ab9a3370e6aae7540092000233502b33504175a6ae854008c118d5d09aba25002232635305d3357380c20bc0b80b626aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a05266a082eb4d5d0a80118231aba135744a004464c6a60ba66ae7018417817016c4d55cf280089baa001357426ae8940088c98d4c164cd5ce02e82d02c02b89aab9e5001137540026ae854010cd40a5d71aba15003335029335505375c40026ae854008c0e0d5d09aba2500223263530553357380b20ac0a80a626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d4005200623020303a357426aae79400c8cccd5cd19b875002480108c07cc110d5d09aab9e500423333573466e1d400d20022301f302f357426aae7940148cccd5cd19b875004480008c088dd71aba135573ca00c464c6a60a066ae7015014413c13813413012c4d55cea80089baa001357426ae8940088c98d4c124cd5ce026825024023882489931a982419ab9c4910350543500049047135573ca00226ea80044d55ce9baa001135744a00226aae7940044dd50009109198008018011000911111111109199999999980080580500480400380300280200180110009109198008018011000891091980080180109000891091980080180109000891091980080180109000909111180200290911118018029091111801002909111180080290008919118011bac0013200135503c2233335573e0024a01c466a01a60086ae84008c00cd5d100101811919191999ab9a3370e6aae75400d200023330073232323333573466e1cd55cea8012400046601a605c6ae854008cd404c0a8d5d09aba25002232635303433573807006a06606426aae7940044dd50009aba150033335500b75ca0146ae854008cd403dd71aba135744a004464c6a606066ae700d00c40bc0b84d5d1280089aab9e5001137540024442466600200800600440024424660020060044002266aa002eb9d6889119118011bab00132001355036223233335573e0044a012466a01066aa05c600c6aae754008c014d55cf280118021aba200302b1357420022244004244244660020080062400224464646666ae68cdc3a800a400046a05e600a6ae84d55cf280191999ab9a3370ea00490011281791931a981399ab9c02b028026025024135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011980318039aba15002375a6ae84d5d1280111931a981219ab9c028025023022135573ca00226ea80048848cc00400c00880048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4c080cd5ce01201080f80f09baa00112232323333573466e1d400520042500723333573466e1d4009200223500a3006357426aae7940108cccd5cd19b87500348000940288c98d4c08ccd5ce01381201101081000f89aab9d50011375400224244460060082244400422444002240024646666ae68cdc3a800a4004400c46666ae68cdc3a80124000400c464c6a603666ae7007c0700680640604d55ce9baa0011220021220012001232323232323333573466e1d4005200c200b23333573466e1d4009200a200d23333573466e1d400d200823300b375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c46601a6eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc048c050d5d0a8049bae357426ae8940248cccd5cd19b875006480088c050c054d5d09aab9e500b23333573466e1d401d2000230133016357426aae7940308c98d4c080cd5ce01201080f80f00e80e00d80d00c80c09aab9d5004135573ca00626aae7940084d55cf280089baa00121222222230070082212222222330060090082122222223005008122222220041222222200322122222223300200900822122222223300100900820012323232323333573466e1d400520022333008375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea00490001180518059aba135573ca00c464c6a602266ae7005404804003c0384d55cea80189aba25001135573ca00226ea80048488c00800c888488ccc00401401000c80048c8c8cccd5cd19b875001480088c018dd71aba135573ca00646666ae68cdc3a80124000460106eb8d5d09aab9e5004232635300b33573801e01801401201026aae7540044dd5000909118010019091180080190008891119191999ab9a3370e6aae75400920002335500b300635742a004600a6ae84d5d1280111931a980419ab9c00c009007006135573ca00226ea800526120012001112212330010030021120014910350543100222123330010040030022001121223002003112200112001120012001122002122001200111232300100122330033002002001332323233322233322233223332223322332233322233223322332233223233322232323322323232323333222232332232323222323222325335301a5335301a333573466e1cc8cccd54c05048004c8cd406488ccd406400c004008d4058004cd4060888c00cc008004800488cdc0000a40040029000199aa98068900091299a980e299a9a81a1a98169a98131a9812001110009110019119a98188011281c11a81c8009080f880e899a8148010008800a8141a981028009111111111005240040380362038266ae712413c53686f756c642062652065786163746c79206f6e652073637269707420696e70757420746f2061766f696420646f75626c65207361742069737375650001b15335303500315335301a5335301a333573466e20ccc064ccd54c03448005402540a0cc020d4c0c00188880094004074074cdc09a9818003111001a80200d80e080e099ab9c49010f73656c6c6572206e6f7420706169640001b15335301a333573466e20ccc064cc88ccd54c03c48005402d40a8cc028004009400401c074075401006c07040704cd5ce24810d66656573206e6f7420706169640001b101b15335301a3322353022002222222222253353503e33355301f1200133502322533535040002210031001503f253353027333573466e3c0300040a40a04d41040045410000c840a4409d4004d4c0c001888800840704cd5ce2491c4f6e6c792073656c6c65722063616e2063616e63656c206f666665720001b101b135301d00122002153353016333573466e2540040d406005c40d4540044cdc199b8235302b001222003480c920d00f2235301a0012222222222333553011120012235302a002222353034003223353038002253353026333573466e3c0500040a009c4cd40cc01401c401c801d40b0024488cd54c02c480048d4d5408c00488cd54098008cd54c038480048d4d5409800488cd540a4008ccd4d540340048cc0e12000001223303900200123303800148000004cd54c02c480048d4d5408c00488cd54098008ccd4d540280048cd54c03c480048d4d5409c00488cd540a8008d5404400400488ccd5540200580080048cd54c03c480048d4d5409c00488cd540a8008d5403c004004ccd55400c044008004444888ccd54c018480054080cd54c02c480048d4d5408c00488cd54098008d54034004ccd54c0184800488d4d54090008894cd4c05cccd54c04048004c8cd405488ccd4d402c00c88008008004d4d402400488004cd4024894cd4c064008406c40040608d4d5409c00488cc028008014018400c4cd409001000d4084004cd54c02c480048d4d5408c00488c8cd5409c00cc004014c8004d540d8894cd4d40900044d5403400c884d4d540a4008894cd4c070cc0300080204cd5404801c0044c01800c00848848cc00400c00848004c8004d540b488448894cd4d40780044008884cc014008ccd54c01c480040140100044484888c00c01044884888cc0080140104484888c004010448004c8004d540a08844894cd4d406000454068884cd406cc010008cd54c01848004010004c8004d5409c88448894cd4d40600044d401800c884ccd4024014c010008ccd54c01c4800401401000448d4d400c0048800448d4d40080048800848848cc00400c0084800488ccd5cd19b8f002001006005222323230010053200135502522335350130014800088d4d54060008894cd4c02cccd5cd19b8f00200900d00c13007001130060033200135502422335350120014800088d4d5405c008894cd4c028ccd5cd19b8f00200700c00b10011300600312200212200120014881002212330010030022001222222222212333333333300100b00a009008007006005004003002200122123300100300220012221233300100400300220011122002122122330010040031200111221233001003002112001221233001003002200121223002003212230010032001222123330010040030022001121223002003112200112001122002122001200122337000040029040497a0088919180080091198019801001000a4411c28f07a93d7715db0bdc1766c8bd5b116602b105c02c54fc3bcd0d4680001",
            &Language::new_plutus_v2()
        ).unwrap();
    assert_eq!(script_v2.language, Language::new_plutus_v2().0);
}

fn redeemer_with_ex_units(mem: &BigNum, steps: &BigNum) -> Redeemer {
    Redeemer::new(
        &RedeemerTag::new_spend(),
        &BigNum::zero(),
        &PlutusData::new_integer(&BigInt::from_str("0").unwrap()),
        &ExUnits::new(mem, steps),
    )
}

#[test]
fn test_total_ex_units() {
    let mut r = Redeemers::new();

    fn assert_ex_units(eu: &ExUnits, exp_mem: u64, exp_steps: u64) {
        assert_eq!(eu.mem, BigNum(exp_mem));
        assert_eq!(eu.steps, BigNum(exp_steps));
    }

    r.add(&redeemer_with_ex_units(&BigNum(10), &BigNum(100)));
    assert_ex_units(&r.total_ex_units().unwrap(), 10, 100);
    r.add(&redeemer_with_ex_units(&BigNum(20), &BigNum(200)));
    assert_ex_units(&r.total_ex_units().unwrap(), 30, 300);
    r.add(&redeemer_with_ex_units(&BigNum(30), &BigNum(300)));
    assert_ex_units(&r.total_ex_units().unwrap(), 60, 600);
}

#[test]
fn test_empty_constr_data() {
    assert_eq!(
        PlutusData::new_empty_constr_plutus_data(&BigNum::one()),
        PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
            &BigNum::from_str("1").unwrap(),
            &PlutusList::new(),
        ),),
    )
}

#[test]
fn test_plutus_script_version() {
    let bytes = hex::decode("4e4d01000033222220051200120011").unwrap();
    let s1: PlutusScript = PlutusScript::from_bytes(bytes.clone()).unwrap();
    let s2: PlutusScript = PlutusScript::from_bytes_v2(bytes.clone()).unwrap();
    let s3: PlutusScript = PlutusScript::from_bytes_v3(bytes.clone()).unwrap();

    assert_eq!(s1.bytes(), bytes[1..]);
    assert_eq!(s2.bytes(), bytes[1..]);
    assert_eq!(s3.bytes(), bytes[1..]);
    assert_eq!(s1.language_version(), Language::new_plutus_v1());
    assert_eq!(s2.language_version(), Language::new_plutus_v2());
    assert_eq!(s3.language_version(), Language::new_plutus_v3());

    assert_eq!(
        s1,
        PlutusScript::from_bytes_with_version(bytes.clone(), &Language::new_plutus_v1(),).unwrap()
    );
    assert_eq!(
        s2,
        PlutusScript::from_bytes_with_version(bytes.clone(), &Language::new_plutus_v2(),).unwrap()
    );
    assert_eq!(
        s3,
        PlutusScript::from_bytes_with_version(bytes.clone(), &Language::new_plutus_v3(),).unwrap()
    );
}

#[test]
fn test_language_roundtrip() {
    fn deserialize_language_from_uint(x: u64) -> Result<Language, DeserializeError> {
        let mut buf = Serializer::new_vec();
        x.serialize(&mut buf).unwrap();
        Language::from_bytes(buf.finalize())
    }

    assert_eq!(
        deserialize_language_from_uint(0).unwrap(),
        Language::new_plutus_v1()
    );
    assert_eq!(
        deserialize_language_from_uint(1).unwrap(),
        Language::new_plutus_v2()
    );
    assert_eq!(
        deserialize_language_from_uint(2).unwrap(),
        Language::new_plutus_v3()
    );
    assert!(deserialize_language_from_uint(3).is_err());

    assert_eq!(
        Language::from_bytes(Language::new_plutus_v1().to_bytes()).unwrap(),
        Language::new_plutus_v1(),
    );
    assert_eq!(
        Language::from_bytes(Language::new_plutus_v2().to_bytes()).unwrap(),
        Language::new_plutus_v2(),
    );
    assert_eq!(
        Language::from_bytes(Language::new_plutus_v3().to_bytes()).unwrap(),
        Language::new_plutus_v3(),
    );
}

#[test]
fn test_cost_model_roundtrip() {
    use crate::TxBuilderConstants;
    let costmodels = TxBuilderConstants::plutus_vasil_cost_models();
    assert_eq!(
        costmodels,
        Costmdls::from_bytes(costmodels.to_bytes()).unwrap()
    );
}

#[test]
fn test_known_plutus_data_hash() {
    use crate::TxBuilderConstants;
    let pdata = PlutusList::from(vec![PlutusData::new_constr_plutus_data(
        &ConstrPlutusData::new(
            &BigNum::zero(),
            &PlutusList::from(vec![
                PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
                    &BigNum::zero(),
                    &PlutusList::from(vec![
                        PlutusData::new_bytes(
                            hex::decode("A183BF86925F66C579A3745C9517744399679B090927B8F6E2F2E1BB")
                                .unwrap(),
                        ),
                        PlutusData::new_bytes(
                            hex::decode("6164617065416D616E734576616E73").unwrap(),
                        ),
                    ]),
                )),
                PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
                    &BigNum::zero(),
                    &PlutusList::from(vec![
                        PlutusData::new_bytes(
                            hex::decode("9A4E855293A0B9AF5E50935A331D83E7982AB5B738EA0E6FC0F9E656")
                                .unwrap(),
                        ),
                        PlutusData::new_bytes(hex::decode("4652414D455F38333030325F4C30").unwrap()),
                    ]),
                )),
                PlutusData::new_bytes(
                    hex::decode("BEA1C521DF58F4EEEF60C647E5EBD88C6039915409F9FD6454A476B9")
                        .unwrap(),
                ),
            ]),
        ),
    )]);
    let redeemers = Redeemers::from(vec![Redeemer::new(
        &RedeemerTag::new_spend(),
        &BigNum::one(),
        &PlutusData::new_empty_constr_plutus_data(&BigNum::zero()),
        &ExUnits::new(&BigNum(7000000), &BigNum(3000000000)),
    )]);
    let lang = Language::new_plutus_v1();
    let lang_costmodel = TxBuilderConstants::plutus_vasil_cost_models()
        .get(&lang)
        .unwrap();
    let mut retained_cost_models = Costmdls::new();
    retained_cost_models.insert(&lang, &lang_costmodel);
    let hash = hash_script_data(&redeemers, &retained_cost_models, Some(pdata));
    assert_eq!(
        hex::encode(hash.to_bytes()),
        "e77f547d8249947bf0af31c432fcfff9c1872b2502b3f34d8107002255695e07"
    );
}

#[test]
fn test_same_datum_in_different_formats_with_expected_hashes() {
    // This is a known datum with indefinite arrays and a known expected hash
    let pdata1 = PlutusData::from_bytes(hex::decode("d8799fd8799f581ca183bf86925f66c579a3745c9517744399679b090927b8f6e2f2e1bb4f616461706541696c656e416d61746fffd8799f581c9a4e855293a0b9af5e50935a331d83e7982ab5b738ea0e6fc0f9e6564e4652414d455f36353030335f4c30ff581cbea1c521df58f4eeef60c647e5ebd88c6039915409f9fd6454a476b9ff").unwrap()).unwrap();
    assert_eq!(
        hex::encode(hash_plutus_data(&pdata1).to_bytes()),
        "ec3028f46325b983a470893a8bdc1b4a100695b635fb1237d301c3490b23e89b"
    );
    // This is the same exact datum manually converted to definite arrays
    // and it produces a different known expected hash because the format is preserved after deserialization
    let pdata2 = PlutusData::from_bytes(hex::decode("d87983d87982581ca183bf86925f66c579a3745c9517744399679b090927b8f6e2f2e1bb4f616461706541696c656e416d61746fd87982581c9a4e855293a0b9af5e50935a331d83e7982ab5b738ea0e6fc0f9e6564e4652414d455f36353030335f4c30581cbea1c521df58f4eeef60c647e5ebd88c6039915409f9fd6454a476b9").unwrap()).unwrap();
    assert_eq!(
        hex::encode(hash_plutus_data(&pdata2).to_bytes()),
        "816cdf6d4d8cba3ad0188ca643db95ddf0e03cdfc0e75a9550a72a82cb146222"
    );
}

#[test]
fn test_known_plutus_data_hash_with_no_datums() {
    let mut costmodels = Costmdls::new();
    costmodels.insert(
        &Language::new_plutus_v2(),
        &TxBuilderConstants::plutus_vasil_cost_models()
            .get(&Language::new_plutus_v2())
            .unwrap(),
    );
    let hash = hash_script_data(
        &Redeemers::from(vec![Redeemer::new(
            &RedeemerTag::new_spend(),
            &BigNum::zero(),
            &PlutusData::new_empty_constr_plutus_data(&BigNum::zero()),
            &ExUnits::new(&BigNum(842996), &BigNum(246100241)),
        )]),
        &costmodels,
        None,
    );
    assert_eq!(
        hex::encode(hash.to_bytes()),
        "5b235dbfaa999fb3616da9903d9affd09c7f2121c2d50db7ece0a9fb8587a038"
    );
}

#[test]
fn test_known_plutus_data_hash_2() {
    let datums = PlutusList::from(vec![PlutusData::new_constr_plutus_data(
        &ConstrPlutusData::new(
            &BigNum::zero(),
            &PlutusList::from(vec![
                PlutusData::new_bytes(
                    hex::decode("45F6A506A49A38263C4A8BBB2E1E369DD8732FB1F9A281F3E8838387")
                        .unwrap(),
                ),
                PlutusData::new_integer(&BigInt::from_str("60000000").unwrap()),
                PlutusData::new_bytes(
                    hex::decode("EE8E37676F6EBB8E031DFF493F88FF711D24AA68666A09D61F1D3FB3")
                        .unwrap(),
                ),
                PlutusData::new_bytes(hex::decode("43727970746F44696E6F3036333039").unwrap()),
            ]),
        ),
    )]);
    let redeemers = Redeemers::from(vec![Redeemer::new(
        &RedeemerTag::new_spend(),
        &BigNum::one(),
        &PlutusData::new_empty_constr_plutus_data(&BigNum::one()),
        &ExUnits::new(&BigNum(61300), &BigNum(18221176)),
    )]);
    let hash = hash_script_data(
        &redeemers,
        &TxBuilderConstants::plutus_vasil_cost_models()
            .retain_language_versions(&Languages(vec![Language::new_plutus_v1()])),
        Some(datums),
    );
    assert_eq!(
        hex::encode(hash.to_bytes()),
        "f3ae8e52bff4c7b8d803469ee61eabf37e96e89f8a3bb80115ad068ab5dff598"
    );
}

#[test]
fn datum_from_enterprise_key_address() {
    let address =
        Address::from_bech32("addr1vxy2c673nsdp0mvgq5d3tpjndngucsytug00k7k6xwlx4lg6dspk5").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}, {\"constructor\": 1, \"fields\": []}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn datum_from_enterprise_script_address() {
    let address =
        Address::from_bech32("addr1w8wrk560wcsldjpnqjamn8s0gn9pdrplpyetrdfpacqrpfs3xezd8").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}, {\"constructor\": 1, \"fields\": []}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn datum_from_base_key_key_address() {
    let address = Address::from_bech32("addr1qxy2c673nsdp0mvgq5d3tpjndngucsytug00k7k6xwlx4lvg434ar8q6zlkcspgmzkr9xmx3e3qghcs7ldad5va7dt7s5efyer").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}, {\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}]}]}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn datum_from_base_script_script_address() {
    let address = Address::from_bech32("addr1x8wrk560wcsldjpnqjamn8s0gn9pdrplpyetrdfpacqrpfku8df57a3p7myrxp9mhx0q73x2z6xr7zfjkx6jrmsqxznqh8u5dz").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}, {\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}]}]}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn datum_from_base_script_key_address() {
    let address = Address::from_bech32("addr1z8wrk560wcsldjpnqjamn8s0gn9pdrplpyetrdfpacqrpf5g434ar8q6zlkcspgmzkr9xmx3e3qghcs7ldad5va7dt7sqx2wxh").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}, {\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}]}]}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn datum_from_base_key_script_address() {
    let address = Address::from_bech32("addr1yxy2c673nsdp0mvgq5d3tpjndngucsytug00k7k6xwlx4lwu8df57a3p7myrxp9mhx0q73x2z6xr7zfjkx6jrmsqxznqrcl7jk").unwrap();
    let datum = PlutusData::from_address(&address).unwrap();
    let orig_datum = PlutusData::from_json("{\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"bytes\": \"88ac6bd19c1a17ed88051b1586536cd1cc408be21efb7ada33be6afd\"}]}, {\"constructor\": 0, \"fields\": [{\"constructor\": 0, \"fields\": [{\"constructor\": 1, \"fields\": [{\"bytes\": \"dc3b534f7621f6c83304bbb99e0f44ca168c3f0932b1b521ee0030a6\"}]}]}]}]}",
                                               PlutusDatumSchema::DetailedSchema).unwrap();
    assert_eq!(datum, orig_datum);
}

#[test]
fn script_data_hash_no_redeemers() {
    let datum = PlutusData::from_hex("d8799fd8799fd8799f581c7fbb4763847b9ec49a132d5359bd86aaecde9275a03aef294ffb79d0ffd8799fd8799fd8799f581cfa34f3b651ecb6a75834c80dc1fd162feb1d1b4cdcef0d065a5785aaffffffffd8799fd8799f581c7fbb4763847b9ec49a132d5359bd86aaecde9275a03aef294ffb79d0ffd8799fd8799fd8799f581cfa34f3b651ecb6a75834c80dc1fd162feb1d1b4cdcef0d065a5785aaffffffffd87a80d8799fd8799f4040ff1a059eb214ff1a001e84801a001e8480ff")
        .unwrap();
    let mut list = PlutusList::from(vec![datum]);
    list.definite_encoding = Some(false);

    let hash = hash_script_data(
        &Redeemers::new(),
        &Costmdls::new(),
        Some(list),
    );
    assert_eq!(
        hex::encode(hash.to_bytes()),
        "fd53a28a846ae6ccf8b221d03d4af122b0b3c442089c05b87e3d86c6792b3ef0"
    );
}

#[test]
fn plutus_data_base_address_roundtrip_keyhash() {
    let payment_cred = Credential::from_keyhash(&fake_key_hash(1));
    let staking_cred = Credential::from_keyhash(&fake_key_hash(2));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let base_address = BaseAddress::new(network_id, &payment_cred, &staking_cred).to_address();
    let plutus_data = PlutusData::from_address(&base_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::testnet_preprod()).unwrap();
    assert_eq!(address_from_data, base_address);
}

#[test]
fn plutus_data_base_address_roundtrip_scripthash() {
    let payment_cred = Credential::from_scripthash(&fake_script_hash(1));
    let staking_cred = Credential::from_scripthash(&fake_script_hash(2));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let base_address = BaseAddress::new(network_id, &payment_cred, &staking_cred).to_address();
    let plutus_data = PlutusData::from_address(&base_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::testnet_preprod()).unwrap();
    assert_eq!(address_from_data, base_address);
}

#[test]
fn plutus_data_enterprise_address_roundtrip_scripthash() {
    let payment_cred = Credential::from_scripthash(&fake_script_hash(1));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let enterprise_address = EnterpriseAddress::new(network_id, &payment_cred).to_address();
    let plutus_data = PlutusData::from_address(&enterprise_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::testnet_preprod()).unwrap();
    assert_eq!(address_from_data, enterprise_address);
}

#[test]
fn plutus_data_enterprise_address_roundtrip_keyhash() {
    let payment_cred = Credential::from_keyhash(&fake_key_hash(1));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let enterprise_address = EnterpriseAddress::new(network_id, &payment_cred).to_address();
    let plutus_data = PlutusData::from_address(&enterprise_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::testnet_preprod()).unwrap();
    assert_eq!(address_from_data, enterprise_address);
}

#[test]
fn plutus_data_pointer_address_roundtrip_keyhash() {
    let pointer = Pointer::new_pointer(&BigNum(1), &BigNum(256), &BigNum(99999999999999999));
    let payment_cred = Credential::from_keyhash(&fake_key_hash(1));
    let network_id = NetworkInfo::mainnet().network_id();
    let pointer_address = PointerAddress::new(network_id, &payment_cred, &pointer).to_address();
    let plutus_data = PlutusData::from_address(&pointer_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::mainnet()).unwrap();
    assert_eq!(address_from_data, pointer_address);
}

#[test]
fn plutus_data_pointer_address_roundtrip_scripthash() {
    let pointer = Pointer::new_pointer(&BigNum(1), &BigNum(256), &BigNum(99999999999999999));
    let payment_cred = Credential::from_scripthash(&fake_script_hash(2));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let pointer_address = PointerAddress::new(network_id, &payment_cred, &pointer).to_address();
    let plutus_data = PlutusData::from_address(&pointer_address).unwrap();
    let address_from_data = plutus_data.as_address(&NetworkInfo::testnet_preprod()).unwrap();
    assert_eq!(address_from_data, pointer_address);
}

#[test]
fn plutus_data_reward_address_error() {
    let payment_cred = Credential::from_keyhash(&fake_key_hash(1));
    let network_id = NetworkInfo::testnet_preprod().network_id();
    let reward_address = RewardAddress::new(network_id, &payment_cred).to_address();

    let plutus_data = PlutusData::from_address(&reward_address);
    assert!(plutus_data.is_err());
}

#[test]
fn plutus_data_byron_address_error() {
    let byron_address = fake_byron_address();
    let plutus_data = PlutusData::from_address(&byron_address);
    assert!(plutus_data.is_err());
}

#[test]
fn plutus_data_malformed_address_error() {
    let malformed_address = MalformedAddress(vec![1, 2 ,3]).to_address();
    let plutus_data = PlutusData::from_address(&malformed_address);
    assert!(plutus_data.is_err());
}