+445
-5
Cargo.lock
+445
-5
Cargo.lock
···
129
129
]
130
130
131
131
[[package]]
132
+
name = "anyhow"
133
+
version = "1.0.100"
134
+
source = "registry+https://github.com/rust-lang/crates.io-index"
135
+
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
136
+
137
+
[[package]]
132
138
name = "ascii"
133
139
version = "1.1.0"
134
140
source = "registry+https://github.com/rust-lang/crates.io-index"
···
488
494
"multihash",
489
495
"serde",
490
496
"serde_bytes",
491
-
"unsigned-varint",
497
+
"unsigned-varint 0.8.0",
492
498
]
493
499
494
500
[[package]]
···
544
550
version = "0.4.3"
545
551
source = "registry+https://github.com/rust-lang/crates.io-index"
546
552
checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3"
553
+
554
+
[[package]]
555
+
name = "cordyceps"
556
+
version = "0.3.4"
557
+
source = "registry+https://github.com/rust-lang/crates.io-index"
558
+
checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a"
559
+
dependencies = [
560
+
"loom",
561
+
"tracing",
562
+
]
547
563
548
564
[[package]]
549
565
name = "core-foundation"
···
666
682
]
667
683
668
684
[[package]]
685
+
name = "curve25519-dalek"
686
+
version = "4.1.3"
687
+
source = "registry+https://github.com/rust-lang/crates.io-index"
688
+
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
689
+
dependencies = [
690
+
"cfg-if",
691
+
"cpufeatures",
692
+
"curve25519-dalek-derive",
693
+
"digest",
694
+
"fiat-crypto",
695
+
"rustc_version",
696
+
"subtle",
697
+
"zeroize",
698
+
]
699
+
700
+
[[package]]
701
+
name = "curve25519-dalek-derive"
702
+
version = "0.1.1"
703
+
source = "registry+https://github.com/rust-lang/crates.io-index"
704
+
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
705
+
dependencies = [
706
+
"proc-macro2",
707
+
"quote",
708
+
"syn 2.0.109",
709
+
]
710
+
711
+
[[package]]
669
712
name = "darling"
670
713
version = "0.21.3"
671
714
source = "registry+https://github.com/rust-lang/crates.io-index"
···
785
828
]
786
829
787
830
[[package]]
831
+
name = "derive_more"
832
+
version = "1.0.0"
833
+
source = "registry+https://github.com/rust-lang/crates.io-index"
834
+
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
835
+
dependencies = [
836
+
"derive_more-impl",
837
+
]
838
+
839
+
[[package]]
840
+
name = "derive_more-impl"
841
+
version = "1.0.0"
842
+
source = "registry+https://github.com/rust-lang/crates.io-index"
843
+
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
844
+
dependencies = [
845
+
"proc-macro2",
846
+
"quote",
847
+
"syn 2.0.109",
848
+
"unicode-xid",
849
+
]
850
+
851
+
[[package]]
852
+
name = "diatomic-waker"
853
+
version = "0.2.3"
854
+
source = "registry+https://github.com/rust-lang/crates.io-index"
855
+
checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c"
856
+
857
+
[[package]]
788
858
name = "digest"
789
859
version = "0.10.7"
790
860
source = "registry+https://github.com/rust-lang/crates.io-index"
···
834
904
]
835
905
836
906
[[package]]
907
+
name = "ed25519"
908
+
version = "2.2.3"
909
+
source = "registry+https://github.com/rust-lang/crates.io-index"
910
+
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
911
+
dependencies = [
912
+
"pkcs8",
913
+
"signature",
914
+
]
915
+
916
+
[[package]]
917
+
name = "ed25519-dalek"
918
+
version = "2.2.0"
919
+
source = "registry+https://github.com/rust-lang/crates.io-index"
920
+
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
921
+
dependencies = [
922
+
"curve25519-dalek",
923
+
"ed25519",
924
+
"rand_core 0.6.4",
925
+
"serde",
926
+
"sha2",
927
+
"subtle",
928
+
"zeroize",
929
+
]
930
+
931
+
[[package]]
837
932
name = "either"
838
933
version = "1.15.0"
839
934
source = "registry+https://github.com/rust-lang/crates.io-index"
···
970
1065
]
971
1066
972
1067
[[package]]
1068
+
name = "fiat-crypto"
1069
+
version = "0.2.9"
1070
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1071
+
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
1072
+
1073
+
[[package]]
973
1074
name = "filetime"
974
1075
version = "0.2.26"
975
1076
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1005
1106
dependencies = [
1006
1107
"futures-core",
1007
1108
"futures-sink",
1008
-
"spin",
1109
+
"spin 0.9.8",
1009
1110
]
1010
1111
1011
1112
[[package]]
···
1040
1141
]
1041
1142
1042
1143
[[package]]
1144
+
name = "futures"
1145
+
version = "0.3.31"
1146
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1147
+
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
1148
+
dependencies = [
1149
+
"futures-channel",
1150
+
"futures-core",
1151
+
"futures-executor",
1152
+
"futures-io",
1153
+
"futures-sink",
1154
+
"futures-task",
1155
+
"futures-util",
1156
+
]
1157
+
1158
+
[[package]]
1159
+
name = "futures-buffered"
1160
+
version = "0.2.12"
1161
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1162
+
checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd"
1163
+
dependencies = [
1164
+
"cordyceps",
1165
+
"diatomic-waker",
1166
+
"futures-core",
1167
+
"pin-project-lite",
1168
+
"spin 0.10.0",
1169
+
]
1170
+
1171
+
[[package]]
1043
1172
name = "futures-channel"
1044
1173
version = "0.3.31"
1045
1174
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1084
1213
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
1085
1214
1086
1215
[[package]]
1216
+
name = "futures-lite"
1217
+
version = "2.6.1"
1218
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1219
+
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
1220
+
dependencies = [
1221
+
"fastrand",
1222
+
"futures-core",
1223
+
"futures-io",
1224
+
"parking",
1225
+
"pin-project-lite",
1226
+
]
1227
+
1228
+
[[package]]
1087
1229
name = "futures-macro"
1088
1230
version = "0.3.31"
1089
1231
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1112
1254
source = "registry+https://github.com/rust-lang/crates.io-index"
1113
1255
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
1114
1256
dependencies = [
1257
+
"futures-channel",
1115
1258
"futures-core",
1116
1259
"futures-io",
1117
1260
"futures-macro",
···
1121
1264
"pin-project-lite",
1122
1265
"pin-utils",
1123
1266
"slab",
1267
+
]
1268
+
1269
+
[[package]]
1270
+
name = "generator"
1271
+
version = "0.8.7"
1272
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1273
+
checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2"
1274
+
dependencies = [
1275
+
"cc",
1276
+
"cfg-if",
1277
+
"libc",
1278
+
"log",
1279
+
"rustversion",
1280
+
"windows",
1124
1281
]
1125
1282
1126
1283
[[package]]
···
1494
1651
"js-sys",
1495
1652
"log",
1496
1653
"wasm-bindgen",
1497
-
"windows-core",
1654
+
"windows-core 0.62.2",
1498
1655
]
1499
1656
1500
1657
[[package]]
···
1618
1775
name = "index"
1619
1776
version = "0.1.0"
1620
1777
dependencies = [
1778
+
"base64 0.22.1",
1621
1779
"env_logger",
1780
+
"ipld-core",
1622
1781
"jacquard",
1782
+
"jacquard-repo",
1623
1783
"log",
1784
+
"serde",
1785
+
"serde_ipld_dagcbor",
1786
+
"serde_json",
1624
1787
"sqlx",
1625
1788
"thiserror 2.0.17",
1626
1789
"tokio",
···
1707
1870
]
1708
1871
1709
1872
[[package]]
1873
+
name = "iroh-car"
1874
+
version = "0.5.1"
1875
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1876
+
checksum = "cb7f8cd4cb9aa083fba8b52e921764252d0b4dcb1cd6d120b809dbfe1106e81a"
1877
+
dependencies = [
1878
+
"anyhow",
1879
+
"cid",
1880
+
"futures",
1881
+
"serde",
1882
+
"serde_ipld_dagcbor",
1883
+
"thiserror 1.0.69",
1884
+
"tokio",
1885
+
"unsigned-varint 0.7.2",
1886
+
]
1887
+
1888
+
[[package]]
1710
1889
name = "is_terminal_polyfill"
1711
1890
version = "1.70.2"
1712
1891
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1777
1956
"bytes",
1778
1957
"chrono",
1779
1958
"cid",
1959
+
"ed25519-dalek",
1780
1960
"getrandom 0.2.16",
1781
1961
"getrandom 0.3.4",
1782
1962
"http",
···
1905
2085
]
1906
2086
1907
2087
[[package]]
2088
+
name = "jacquard-repo"
2089
+
version = "0.9.2"
2090
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2091
+
checksum = "2ccdadfea11df142fbfb11cf7e5c1f7b8c0548758dedb0ce0eac182777f91f18"
2092
+
dependencies = [
2093
+
"bytes",
2094
+
"cid",
2095
+
"ed25519-dalek",
2096
+
"iroh-car",
2097
+
"jacquard-common",
2098
+
"jacquard-derive",
2099
+
"k256",
2100
+
"miette",
2101
+
"multihash",
2102
+
"n0-future",
2103
+
"p256",
2104
+
"serde",
2105
+
"serde_bytes",
2106
+
"serde_ipld_dagcbor",
2107
+
"sha2",
2108
+
"smol_str",
2109
+
"thiserror 2.0.17",
2110
+
"tokio",
2111
+
"trait-variant",
2112
+
]
2113
+
2114
+
[[package]]
1908
2115
name = "jiff"
1909
2116
version = "0.2.16"
1910
2117
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2005
2212
"cfg-if",
2006
2213
"ecdsa",
2007
2214
"elliptic-curve",
2215
+
"once_cell",
2008
2216
"sha2",
2217
+
"signature",
2009
2218
]
2010
2219
2011
2220
[[package]]
···
2025
2234
source = "registry+https://github.com/rust-lang/crates.io-index"
2026
2235
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
2027
2236
dependencies = [
2028
-
"spin",
2237
+
"spin 0.9.8",
2029
2238
]
2030
2239
2031
2240
[[package]]
···
2095
2304
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
2096
2305
2097
2306
[[package]]
2307
+
name = "loom"
2308
+
version = "0.7.2"
2309
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2310
+
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
2311
+
dependencies = [
2312
+
"cfg-if",
2313
+
"generator",
2314
+
"scoped-tls",
2315
+
"tracing",
2316
+
"tracing-subscriber",
2317
+
]
2318
+
2319
+
[[package]]
2098
2320
name = "lru-cache"
2099
2321
version = "0.1.2"
2100
2322
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2150
2372
"proc-macro2",
2151
2373
"quote",
2152
2374
"syn 1.0.109",
2375
+
]
2376
+
2377
+
[[package]]
2378
+
name = "matchers"
2379
+
version = "0.2.0"
2380
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2381
+
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
2382
+
dependencies = [
2383
+
"regex-automata",
2153
2384
]
2154
2385
2155
2386
[[package]]
···
2268
2499
dependencies = [
2269
2500
"core2",
2270
2501
"serde",
2271
-
"unsigned-varint",
2502
+
"unsigned-varint 0.8.0",
2272
2503
]
2273
2504
2274
2505
[[package]]
···
2290
2521
]
2291
2522
2292
2523
[[package]]
2524
+
name = "n0-future"
2525
+
version = "0.1.3"
2526
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2527
+
checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794"
2528
+
dependencies = [
2529
+
"cfg_aliases",
2530
+
"derive_more",
2531
+
"futures-buffered",
2532
+
"futures-lite",
2533
+
"futures-util",
2534
+
"js-sys",
2535
+
"pin-project",
2536
+
"send_wrapper",
2537
+
"tokio",
2538
+
"tokio-util",
2539
+
"wasm-bindgen",
2540
+
"wasm-bindgen-futures",
2541
+
"web-time",
2542
+
]
2543
+
2544
+
[[package]]
2293
2545
name = "ndk-context"
2294
2546
version = "0.1.1"
2295
2547
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2309
2561
dependencies = [
2310
2562
"memchr",
2311
2563
"minimal-lexical",
2564
+
]
2565
+
2566
+
[[package]]
2567
+
name = "nu-ansi-term"
2568
+
version = "0.50.3"
2569
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2570
+
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
2571
+
dependencies = [
2572
+
"windows-sys 0.61.2",
2312
2573
]
2313
2574
2314
2575
[[package]]
···
2548
2809
]
2549
2810
2550
2811
[[package]]
2812
+
name = "pin-project"
2813
+
version = "1.1.10"
2814
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2815
+
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
2816
+
dependencies = [
2817
+
"pin-project-internal",
2818
+
]
2819
+
2820
+
[[package]]
2821
+
name = "pin-project-internal"
2822
+
version = "1.1.10"
2823
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2824
+
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
2825
+
dependencies = [
2826
+
"proc-macro2",
2827
+
"quote",
2828
+
"syn 2.0.109",
2829
+
]
2830
+
2831
+
[[package]]
2551
2832
name = "pin-project-lite"
2552
2833
version = "0.2.16"
2553
2834
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3032
3313
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
3033
3314
3034
3315
[[package]]
3316
+
name = "rustc_version"
3317
+
version = "0.4.1"
3318
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3319
+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
3320
+
dependencies = [
3321
+
"semver",
3322
+
]
3323
+
3324
+
[[package]]
3035
3325
name = "rustix"
3036
3326
version = "1.1.2"
3037
3327
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3131
3421
]
3132
3422
3133
3423
[[package]]
3424
+
name = "scoped-tls"
3425
+
version = "1.0.1"
3426
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3427
+
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
3428
+
3429
+
[[package]]
3134
3430
name = "scopeguard"
3135
3431
version = "1.2.0"
3136
3432
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3161
3457
]
3162
3458
3163
3459
[[package]]
3460
+
name = "send_wrapper"
3461
+
version = "0.6.0"
3462
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3463
+
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
3464
+
3465
+
[[package]]
3164
3466
name = "serde"
3165
3467
version = "1.0.228"
3166
3468
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3321
3623
]
3322
3624
3323
3625
[[package]]
3626
+
name = "sharded-slab"
3627
+
version = "0.1.7"
3628
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3629
+
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
3630
+
dependencies = [
3631
+
"lazy_static",
3632
+
]
3633
+
3634
+
[[package]]
3324
3635
name = "shlex"
3325
3636
version = "1.3.0"
3326
3637
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3418
3729
]
3419
3730
3420
3731
[[package]]
3732
+
name = "spin"
3733
+
version = "0.10.0"
3734
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3735
+
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
3736
+
3737
+
[[package]]
3421
3738
name = "spki"
3422
3739
version = "0.7.3"
3423
3740
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3829
4146
]
3830
4147
3831
4148
[[package]]
4149
+
name = "thread_local"
4150
+
version = "1.1.9"
4151
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4152
+
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
4153
+
dependencies = [
4154
+
"cfg-if",
4155
+
]
4156
+
4157
+
[[package]]
3832
4158
name = "threadpool"
3833
4159
version = "1.8.1"
3834
4160
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3963
4289
"bytes",
3964
4290
"futures-core",
3965
4291
"futures-sink",
4292
+
"futures-util",
3966
4293
"pin-project-lite",
3967
4294
"tokio",
3968
4295
]
···
4042
4369
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
4043
4370
dependencies = [
4044
4371
"once_cell",
4372
+
"valuable",
4373
+
]
4374
+
4375
+
[[package]]
4376
+
name = "tracing-log"
4377
+
version = "0.2.0"
4378
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4379
+
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
4380
+
dependencies = [
4381
+
"log",
4382
+
"once_cell",
4383
+
"tracing-core",
4384
+
]
4385
+
4386
+
[[package]]
4387
+
name = "tracing-subscriber"
4388
+
version = "0.3.20"
4389
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4390
+
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
4391
+
dependencies = [
4392
+
"matchers",
4393
+
"nu-ansi-term",
4394
+
"once_cell",
4395
+
"regex-automata",
4396
+
"sharded-slab",
4397
+
"smallvec",
4398
+
"thread_local",
4399
+
"tracing",
4400
+
"tracing-core",
4401
+
"tracing-log",
4045
4402
]
4046
4403
4047
4404
[[package]]
···
4128
4485
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
4129
4486
4130
4487
[[package]]
4488
+
name = "unicode-xid"
4489
+
version = "0.2.6"
4490
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4491
+
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
4492
+
4493
+
[[package]]
4494
+
name = "unsigned-varint"
4495
+
version = "0.7.2"
4496
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4497
+
checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105"
4498
+
4499
+
[[package]]
4131
4500
name = "unsigned-varint"
4132
4501
version = "0.8.0"
4133
4502
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4174
4543
version = "0.2.2"
4175
4544
source = "registry+https://github.com/rust-lang/crates.io-index"
4176
4545
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
4546
+
4547
+
[[package]]
4548
+
name = "valuable"
4549
+
version = "0.1.1"
4550
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4551
+
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
4177
4552
4178
4553
[[package]]
4179
4554
name = "vcpkg"
···
4381
4756
]
4382
4757
4383
4758
[[package]]
4759
+
name = "windows"
4760
+
version = "0.61.3"
4761
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4762
+
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
4763
+
dependencies = [
4764
+
"windows-collections",
4765
+
"windows-core 0.61.2",
4766
+
"windows-future",
4767
+
"windows-link 0.1.3",
4768
+
"windows-numerics",
4769
+
]
4770
+
4771
+
[[package]]
4772
+
name = "windows-collections"
4773
+
version = "0.2.0"
4774
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4775
+
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
4776
+
dependencies = [
4777
+
"windows-core 0.61.2",
4778
+
]
4779
+
4780
+
[[package]]
4781
+
name = "windows-core"
4782
+
version = "0.61.2"
4783
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4784
+
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
4785
+
dependencies = [
4786
+
"windows-implement",
4787
+
"windows-interface",
4788
+
"windows-link 0.1.3",
4789
+
"windows-result 0.3.4",
4790
+
"windows-strings 0.4.2",
4791
+
]
4792
+
4793
+
[[package]]
4384
4794
name = "windows-core"
4385
4795
version = "0.62.2"
4386
4796
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4391
4801
"windows-link 0.2.1",
4392
4802
"windows-result 0.4.1",
4393
4803
"windows-strings 0.5.1",
4804
+
]
4805
+
4806
+
[[package]]
4807
+
name = "windows-future"
4808
+
version = "0.2.1"
4809
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4810
+
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
4811
+
dependencies = [
4812
+
"windows-core 0.61.2",
4813
+
"windows-link 0.1.3",
4814
+
"windows-threading",
4394
4815
]
4395
4816
4396
4817
[[package]]
···
4426
4847
version = "0.2.1"
4427
4848
source = "registry+https://github.com/rust-lang/crates.io-index"
4428
4849
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
4850
+
4851
+
[[package]]
4852
+
name = "windows-numerics"
4853
+
version = "0.2.0"
4854
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4855
+
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
4856
+
dependencies = [
4857
+
"windows-core 0.61.2",
4858
+
"windows-link 0.1.3",
4859
+
]
4429
4860
4430
4861
[[package]]
4431
4862
name = "windows-registry"
···
4580
5011
"windows_x86_64_gnu 0.53.1",
4581
5012
"windows_x86_64_gnullvm 0.53.1",
4582
5013
"windows_x86_64_msvc 0.53.1",
5014
+
]
5015
+
5016
+
[[package]]
5017
+
name = "windows-threading"
5018
+
version = "0.1.0"
5019
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5020
+
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
5021
+
dependencies = [
5022
+
"windows-link 0.1.3",
4583
5023
]
4584
5024
4585
5025
[[package]]
+6
Cargo.toml
+6
Cargo.toml
···
4
4
edition = "2024"
5
5
6
6
[dependencies]
7
+
base64 = "0.22.1"
7
8
env_logger = "0.11.8"
9
+
ipld-core = "0.4.2"
8
10
jacquard = "0.9.0"
11
+
jacquard-repo = "0.9.2"
9
12
log = "0.4.28"
13
+
serde = "1.0.228"
14
+
serde_ipld_dagcbor = "0.6.4"
15
+
serde_json = { version = "1.0.145", features = ["raw_value"] }
10
16
sqlx = { version = "0.8.6", features = ["runtime-tokio", "postgres"] }
11
17
thiserror = "2.0.17"
12
18
tokio = "1.48.0"
+68
src/backfill/load_car.rs
+68
src/backfill/load_car.rs
···
1
+
use jacquard::api::com_atproto;
2
+
use jacquard::client::Agent;
3
+
use jacquard::types::{did::Did, tid::Tid};
4
+
use jacquard::url::Url;
5
+
use jacquard::xrpc::XrpcExt;
6
+
use jacquard_repo::commit::Commit;
7
+
use jacquard_repo::{BlockStore, MemoryBlockStore, Mst};
8
+
use std::sync::Arc;
9
+
use thiserror::Error;
10
+
11
+
#[derive(Error, Debug)]
12
+
pub enum Error {
13
+
#[error("Error loading car file: {}", .0)]
14
+
ClientError(#[from] jacquard::error::ClientError),
15
+
#[error("Error loading car file: {}", .0)]
16
+
RepoError(#[from] jacquard_repo::RepoError),
17
+
#[error("Missing root block from car file (malformed car file)")]
18
+
MissingRoot,
19
+
}
20
+
21
+
pub struct Car {
22
+
pub storage: MemoryBlockStore,
23
+
pub mst: Mst<MemoryBlockStore>,
24
+
pub rev: Tid,
25
+
}
26
+
27
+
impl PartialEq<Tid> for Car {
28
+
fn eq(&self, other: &Tid) -> bool {
29
+
&self.rev == other
30
+
}
31
+
}
32
+
33
+
use std::cmp::Ordering;
34
+
impl PartialOrd<Tid> for Car {
35
+
fn partial_cmp(&self, other: &Tid) -> Option<Ordering> {
36
+
return match self.rev.compare_to(other) {
37
+
1 => Some(Ordering::Greater),
38
+
0 => Some(Ordering::Equal),
39
+
-1 => Some(Ordering::Less),
40
+
_ => None,
41
+
};
42
+
}
43
+
}
44
+
45
+
pub async fn load_car(user: Did<'_>, pds: Url) -> Result<Car, Error> {
46
+
let agent = Agent::unauthenticated();
47
+
let req = com_atproto::sync::get_repo::GetRepo::new()
48
+
.did(user)
49
+
.build();
50
+
let res = agent.xrpc(pds).send(&req).await?;
51
+
52
+
let car = res.buffer();
53
+
let car = jacquard_repo::car::parse_car_bytes(&car).await?;
54
+
55
+
let storage = jacquard_repo::storage::MemoryBlockStore::new_from_blocks(car.blocks);
56
+
57
+
let root = storage
58
+
.get(&car.root)
59
+
.await?
60
+
.ok_or_else(|| Error::MissingRoot)?;
61
+
let root = Commit::from_cbor(&root)?;
62
+
let rev = root.rev().to_owned();
63
+
let root = root.data();
64
+
65
+
let mst = Mst::load(Arc::new(storage.clone()), *root, None);
66
+
67
+
Ok(Car { storage, mst, rev })
68
+
}
+138
src/backfill/mod.rs
+138
src/backfill/mod.rs
···
1
+
use std::{cmp::Ordering, str::FromStr};
2
+
3
+
use jacquard::{types::tid::Tid, url::Url};
4
+
use sqlx::{Pool, Postgres, query};
5
+
use thiserror::Error;
6
+
7
+
use crate::{
8
+
backfill::{load_car::load_car, parse_car::parse_car},
9
+
config,
10
+
};
11
+
12
+
pub mod load_car;
13
+
pub mod parse_car;
14
+
15
+
const DB_MAX_REQ: usize = 65535;
16
+
17
+
#[derive(Error, Debug)]
18
+
pub enum Error {
19
+
#[error("Error parsing TID: {}", .0)]
20
+
TidParse(#[from] jacquard::types::string::AtStrError),
21
+
#[error("{}", .0)]
22
+
GetCarError(#[from] crate::backfill::load_car::Error),
23
+
#[error(
24
+
"The database claims to be more up to date than the PDS.
25
+
Most likely either the PDS or repo is broken, or the database has been corrupted.
26
+
Check your PDS repo is working and/or drop the database."
27
+
)]
28
+
DbTidTooLow,
29
+
#[error("Database error: {}", .0)]
30
+
DbError(#[from] sqlx::Error),
31
+
#[error("{}", .0)]
32
+
ParseCarError(#[from] crate::backfill::parse_car::Error),
33
+
}
34
+
35
+
/// backfill works as follows (https://docs.bsky.app/docs/advanced-guides/backfill)
36
+
///
37
+
/// 1. resolve did -> pds
38
+
/// 2. stream com.atproto.sync.subscribeRepos to a buffer
39
+
/// 3. get a car file from com.atproto.sync.getRepo (diff if a rev is stored in database)
40
+
/// 4. apply car file diff to database (incl rev)
41
+
/// 5. start playing events from buffer
42
+
/// 1. drop all events from other users
43
+
/// 2. drop all events with a lower rev than current rev
44
+
/// 3. apply event & update rev
45
+
/// 4. (non blocking) get blobs if missing
46
+
/// 5. (non blocking) parse for strongref and store strongrefs
47
+
/// 6. (non blocking) trigger garbage collection of blobs and strongref
48
+
/// 6. once buffer is empty, parse events live
49
+
pub async fn backfill(pds: &str, conn: &Pool<Postgres>) -> Result<(), Error> {
50
+
let db_rev = if let Some(rev) = query!(
51
+
"SELECT (rev) FROM meta WHERE did = $1",
52
+
config::USER.to_string()
53
+
)
54
+
.fetch_one(conn)
55
+
.await
56
+
.ok()
57
+
.and_then(|x| x.rev)
58
+
{
59
+
Tid::from_str(&rev)?
60
+
} else {
61
+
Tid::from_time(0, 0)
62
+
};
63
+
64
+
let pds = Url::from_str(&format!("https://{pds}/")).unwrap();
65
+
let car = load_car(config::USER.clone(), pds).await?;
66
+
67
+
match car.partial_cmp(&db_rev) {
68
+
Some(val) => match val {
69
+
// car rev newer than db rev
70
+
// continue on; every other branch diverges
71
+
Ordering::Greater => {}
72
+
// revisions are the same so we can skip backfill
73
+
Ordering::Equal => return Ok(()),
74
+
// db rev newer than car rev
75
+
// this means the db or car file is borked
76
+
// panic out and let the user deal with things
77
+
Ordering::Less => return Err(Error::DbTidTooLow),
78
+
// panic!(
79
+
// r"The database claims to be more up to date than the PDS.
80
+
// Most likely either the PDS or repo is broken, or the database has been corrupted.
81
+
// Check your PDS repo is working and/or drop the database."
82
+
// ),
83
+
},
84
+
// cant compare rev so assume all is ok and continue
85
+
None => {}
86
+
};
87
+
88
+
// erase all old records and return if it fails
89
+
// we dont use diffs bc theyre complex and the overhead is minimal rn
90
+
// only real overhead is network latency which would be ~= anyway
91
+
let _ = query!("DELETE FROM records").execute(conn).await?;
92
+
93
+
let data = parse_car(&car).await?;
94
+
let mut data = data.chunks(DB_MAX_REQ / 4);
95
+
96
+
while let Some(data) = data.next() {
97
+
let mut query = sqlx::QueryBuilder::new("INSERT INTO records(collection, rkey, record) ");
98
+
query.push_values(
99
+
data,
100
+
|mut b: sqlx::query_builder::Separated<'_, '_, Postgres, &'static str>, data| {
101
+
b.push_bind(data.0.0.clone())
102
+
.push_bind(data.0.1.clone())
103
+
.push_bind(data.1.clone());
104
+
},
105
+
);
106
+
107
+
match query.build().execute(conn).await {
108
+
Err(err) => {
109
+
// couldnt backfill so go nuclear
110
+
// this is program startup so its prolly safe lol
111
+
println!("Got error \"{}\"\nDeleting records and exiting...", err);
112
+
let _ = query!("DELETE FROM records").execute(conn).await?;
113
+
panic!()
114
+
}
115
+
_ => {}
116
+
};
117
+
}
118
+
119
+
match query!(
120
+
"UPDATE meta SET rev = $1 WHERE did = $2",
121
+
car.rev.to_string(),
122
+
config::USER.to_string()
123
+
)
124
+
.execute(conn)
125
+
.await
126
+
{
127
+
Err(err) => {
128
+
// couldnt save tid so go nuclear
129
+
// this is program startup so its prolly safe lol
130
+
println!("Got error \"{}\"\nDeleting records and exiting...", err);
131
+
let _ = query!("DELETE FROM records").execute(conn).await?;
132
+
panic!()
133
+
}
134
+
_ => {}
135
+
};
136
+
137
+
Ok(())
138
+
}
+69
src/backfill/parse_car.rs
+69
src/backfill/parse_car.rs
···
1
+
use std::iter::zip;
2
+
3
+
use ipld_core::{cid::CidGeneric, ipld::Ipld};
4
+
use jacquard::smol_str::SmolStr;
5
+
use jacquard_repo::BlockStore;
6
+
use serde_json::Value;
7
+
use thiserror::Error;
8
+
9
+
use crate::{backfill::load_car::Car, utils::ipld_json::ipld_to_json_value};
10
+
11
+
#[derive(Debug, Error)]
12
+
pub enum Error {
13
+
#[error("Error getting records from car file: {}", .0)]
14
+
RepoError(#[from] jacquard_repo::RepoError),
15
+
#[error("Missing CID from car file")]
16
+
MissingCid,
17
+
#[error("Could not decode record: {}", .0)]
18
+
DecodeError(#[from] serde_ipld_dagcbor::DecodeError<std::convert::Infallible>),
19
+
#[error("Could not convert into json: {}", .0)]
20
+
IpldToJsonError(#[from] crate::utils::ipld_json::Error),
21
+
#[error("Could not break {} into a collection and rkey", .0)]
22
+
MalformedRecordKey(SmolStr),
23
+
}
24
+
25
+
pub type AccountData = Vec<((String, String), Value)>;
26
+
27
+
pub async fn parse_car(car: &Car) -> Result<AccountData, Error> {
28
+
let (keys, records): (Vec<SmolStr>, Vec<CidGeneric<64>>) =
29
+
car.mst.leaves().await?.into_iter().unzip();
30
+
31
+
// convert keys into (collection, rkey)
32
+
let keys = keys
33
+
.into_iter()
34
+
.map(|x| {
35
+
let mut parts = x.split('/');
36
+
let collection = parts.next();
37
+
let rkey = parts.next();
38
+
if parts.next().is_none()
39
+
&& let Some(collection) = collection
40
+
&& let Some(rkey) = rkey
41
+
{
42
+
Ok::<_, Error>((collection.to_string(), rkey.to_string()))
43
+
} else {
44
+
Err(Error::MalformedRecordKey(x))
45
+
}
46
+
})
47
+
.collect::<Result<Vec<_>, _>>()?;
48
+
49
+
// convert records into Value
50
+
let records = &records[..];
51
+
let records = car
52
+
.storage
53
+
.get_many(records)
54
+
.await?
55
+
.into_iter()
56
+
.collect::<Option<Vec<_>>>()
57
+
.ok_or_else(|| Error::MissingCid)?
58
+
.into_iter()
59
+
.map(|x| {
60
+
let data = serde_ipld_dagcbor::from_slice::<Ipld>(&x)?;
61
+
let value = ipld_to_json_value(&data)?;
62
+
Ok::<_, Error>(value)
63
+
})
64
+
.collect::<Result<Vec<_>, _>>()?;
65
+
66
+
let data = zip(keys, records).collect::<Vec<((_, _), _)>>();
67
+
68
+
Ok(data)
69
+
}
+9
src/main.rs
+9
src/main.rs
···
1
1
use sqlx::{Pool, Postgres};
2
2
3
+
use crate::backfill::backfill;
4
+
5
+
mod backfill;
3
6
mod config;
4
7
mod db;
5
8
mod utils;
···
14
17
let pds = match utils::resolver::resolve(&config::USER).await {
15
18
Ok(val) => val,
16
19
Err(err) => panic!("{}", err),
20
+
};
21
+
22
+
let backfilled = backfill(&pds, &conn).await;
23
+
if let Err(err) = backfilled {
24
+
println!("{}", err);
25
+
return Err(());
17
26
};
18
27
19
28
println!("Completed sucessfully!");
+54
src/utils/ipld_json.rs
+54
src/utils/ipld_json.rs
···
1
+
use base64::{Engine, prelude::BASE64_STANDARD_NO_PAD};
2
+
use ipld_core::{cid::multibase::Base, ipld::Ipld};
3
+
use log::warn;
4
+
use serde_json::{Map, Number, Value, json};
5
+
use thiserror::Error;
6
+
7
+
#[derive(Error, Debug)]
8
+
pub enum Error {
9
+
#[error("CID error: {}", .0)]
10
+
CidError(#[from] ipld_core::cid::Error),
11
+
#[error("Number too big: {0} > {1} || {0} < {2}", .val, u64::MAX, i64::MIN)]
12
+
IntInvalidSize { val: i128 },
13
+
#[error("{} was NaN or Infinity", .0)]
14
+
FloatInvalidSize(f64),
15
+
}
16
+
17
+
/// Convert any decoded IPLD data into serde_json Value
18
+
///
19
+
/// This can be used for `sqlx` queries or decoded into plain JSON
20
+
///
21
+
/// We can't use bog standard `to_string` or `to_json` functions
22
+
/// due to the fact that ATProto DAG-CBOR does not map straight
23
+
/// to ATProto JSON (see: `Ipld::Bytes` and `Ipld::Link` in the function definition.)
24
+
///
25
+
/// To get an atproto JSON representation in string format call
26
+
/// `Value::to_string(&self)` on the Value from this function
27
+
pub fn ipld_to_json_value(data: &Ipld) -> Result<Value, Error> {
28
+
Ok(match data {
29
+
Ipld::Null => Value::Null,
30
+
Ipld::Bool(bool) => Value::Bool(*bool),
31
+
Ipld::Integer(int) => Value::Number(
32
+
Number::from_i128(*int).ok_or_else(|| Error::IntInvalidSize { val: *int })?,
33
+
),
34
+
Ipld::Float(float) => {
35
+
warn!("Got float in IPLD data: {}", float);
36
+
Value::Number(Number::from_f64(*float).ok_or_else(|| Error::FloatInvalidSize(*float))?)
37
+
}
38
+
Ipld::String(str) => Value::String(str.clone()),
39
+
Ipld::Bytes(items) => json!({ "$bytes": BASE64_STANDARD_NO_PAD.encode(items) }),
40
+
Ipld::List(iplds) => Value::Array(
41
+
iplds
42
+
.into_iter()
43
+
.map(|x| ipld_to_json_value(x))
44
+
.collect::<Result<Vec<_>, _>>()?,
45
+
),
46
+
Ipld::Map(map) => Value::Object(
47
+
map.into_iter()
48
+
.map(|(k, v)| Ok::<_, Error>((k.clone(), ipld_to_json_value(v)?)))
49
+
.collect::<Result<Map<String, Value>, _>>()?,
50
+
),
51
+
Ipld::Link(cid) => json!({"$link":
52
+
cid.to_string_of_base(Base::Base32Lower)? }),
53
+
})
54
+
}