├── .gitignore ├── src ├── main.rs └── lib.rs ├── Cargo.toml ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fhe-auctions" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | tfhe = {git = "https://github.com/Janmajayamall/tfhe-rs.git", features = ["boolean", "shortint", "integer", "p-encoding","aarch64-unix"]} 10 | rand = "0.8.5" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FHE auctions 2 | 3 | Implements bit slice approach for private auctions as described in [2002/189](https://eprint.iacr.org/2002/189). 4 | 5 | Uses [tfhe-rs](https://github.com/zama-ai/tfhe-rs) to implement boolean gates using p-encoding technique as described in [2023/1589](https://eprint.iacr.org/2023/1589.pdf). 6 | 7 | TFHE parameters are obtained via concrete-optimiser and has 128-bit of security. 8 | 9 | # Costs 10 | 11 | Auction circuit runtime increase linearly with $k$ and $n$, where $n$ is no. of bidders and $k$ is bits in bid (for ex, 64 bits, 128 bits) 12 | 13 | Since a bid of $k$ bits is represented as $k$ LWE ciphertexts, each bidder needs to upload $k$ LWE ciphertexts. 14 | 15 | # Test 16 | 17 | On x86_64 based machines set `tfhe-rs` dependecy in cargo.toml as 18 | 19 | `tfhe = {git = "https://github.com/Janmajayamall/tfhe-rs.git", features = ["boolean", "shortint", "integer", "p-encoding","x86_64-unix"]}` 20 | 21 | On apple-silicon or aarch-64 based machines set `tfhe-rs` dependecy in cargo.toml as 22 | 23 | `tfhe = {git = "https://github.com/Janmajayamall/tfhe-rs.git", features = ["boolean", "shortint", "integer", "p-encoding","aarch64-unix"]}` 24 | 25 | then run `cargo test --release tests::auction_circuit_works -- --nocapture` 26 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use tfhe::gadget::{ciphertext::Ciphertext, server_key::ServerKey}; 2 | 3 | fn auction_circuit( 4 | server_key: &ServerKey, 5 | bids: &Vec>, 6 | bid_bits: usize, 7 | bidder_count: usize, 8 | ) -> Result<(Vec, Vec), Box> { 9 | //TODO: check bids are correctly formed 10 | 11 | let mut w = vec![Ciphertext::Trivial(true); bidder_count]; 12 | let mut s = vec![Ciphertext::Placeholder; bidder_count]; 13 | let mut amount = vec![Ciphertext::Placeholder; bid_bits]; 14 | for i in 0..bid_bits { 15 | // let now = std::time::Instant::now(); 16 | for j in 0..bidder_count { 17 | // AND at i^th MSB of j^th bidder 18 | s[j] = server_key.and(&w[j], &bids[j][i])?; 19 | } 20 | 21 | // OR 22 | let b = { 23 | let mut b = server_key.or(&s[0], &s[1])?; 24 | for j in 2..bidder_count { 25 | b = server_key.or(&b, &s[j])?; 26 | } 27 | b 28 | }; 29 | 30 | // We require a multiplexer here and there are few ways to implement it: 31 | // 1. Circuit bootstrapping: Circuit bootstrap $b$ to a GGSW ciphertext and then use a single CMUX operation. However circuit bootstrapping itself requires $pbslevel$ bootstrapping operations + $pbslevel$ LWE -> RLWE key switching operations. Moreover, it requires private functional key switching keys. I don't think circuit bootstrapping improves runtime significantly such that it is worth it deal with its complexity + introducing more keys. 32 | // 2. Switch to 7-encoding space: In 7-encoding space this operation can be evaluated as single bootstrapping operation. However, p=7 requires 3 bit plaintext space thus doubling the bootstrapping runtime as compared to 2 bit plaintext space. Let bootstrapping runtime with 2-bit plaintext be x. Then evaluating AND + OR + MULTIPLEXER (MULTIPLEXER = $bs$ + $!bw$) takes 5x. With 3-bit plaintext space bootstrapping runtime equals 2x. Evaluating AND + OR + MULTIPLEXER (MULTIPLEXER is a single bootstrap) takes 5x. Thus, there's no benefit of switching to 7-encoding space. 33 | // 3. Rewriting multiplexer as $b * (s - w) + w$: This assumes ciphertexts are in canonical encoding (i.e. either 0/1 instead of 1/2). Switching from 1/2 to 0/1 is trivial since it requires a single plaintext subtraction by 1. However, $s - w$ may equal -1 which will equal 2 in modulus 3. This forces lookup table to output to different values at same input (input: 1,0), which isn't possible. 34 | // 4. Naively implementation the multiplexer as $b s || !bw$: We implement this for now. However this requires 3 bootstrapping operations causing this to be the most expensive part of the circuit. 35 | // 5. Decrypting $b$: Since $b$ has to decrypted anyways to learn amount (assuming highest price auction), decrypting it before evaluating the multiplexer can save us from implementation it. 36 | // AND to reset w 37 | let b_not = server_key.not(&b); 38 | for j in 0..bidder_count { 39 | // (b & s[j]) + (!b & w[j]) 40 | let c0 = server_key.and(&b, &s[j])?; 41 | let c1 = server_key.and(&b_not, &w[j])?; 42 | w[j] = server_key.or(&c0, &c1)?; 43 | } 44 | // println!("Time i:{i} - {}", now.elapsed().as_millis()); 45 | // set i^th MSB of amount 46 | amount[i] = b; 47 | } 48 | 49 | Ok((w, amount)) 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use rand::{thread_rng, Rng}; 55 | use tfhe::gadget::{boolean::BOOLEAN_PARAMETERS, gen_keys}; 56 | 57 | use super::*; 58 | 59 | #[test] 60 | fn auction_circuit_works() -> Result<(), Box> { 61 | let bidders = 50; 62 | let BID_BITS = 64; 63 | 64 | let bids = (0..bidders) 65 | .into_iter() 66 | .map(|_| thread_rng().gen::()) 67 | .collect::>(); 68 | 69 | // generate FHE keys 70 | let (client_key, server_key) = gen_keys(&BOOLEAN_PARAMETERS); 71 | 72 | // encrypt bids 73 | let encrypts_bid_vector = bids 74 | .iter() 75 | .map(|bid_amount| { 76 | // encrypt bits from MSB to LSB 77 | (0..BID_BITS) 78 | .into_iter() 79 | .map(|i| { 80 | let bit_i = (bid_amount >> (BID_BITS - 1 - i)) & 1; 81 | client_key.encrypt(bit_i != 0) 82 | }) 83 | .collect::>() 84 | }) 85 | .collect::>>(); 86 | 87 | let now = std::time::Instant::now(); 88 | let (winner_identity_bit, winning_amount_bits) = 89 | auction_circuit(&server_key, &encrypts_bid_vector, BID_BITS, bidders)?; 90 | println!("Auction runtime: {}ms", now.elapsed().as_millis()); 91 | 92 | // find the highest bidder amount 93 | let expected_highest_bid_amount = bids.iter().max().unwrap(); 94 | let mut expected_highest_bidder_identity = vec![]; 95 | bids.iter().enumerate().for_each(|(index, bid)| { 96 | if bid == expected_highest_bid_amount { 97 | expected_highest_bidder_identity.push(index); 98 | } 99 | }); 100 | 101 | // check correctness 102 | // construct highest bidding amout returned from auction circuit 103 | let mut res_highest_bid_amount = 0u64; 104 | // winning amounts bits are stored from MSB to LSB 105 | winning_amount_bits 106 | .iter() 107 | .enumerate() 108 | .for_each(|(index, ct)| { 109 | let bit = client_key.decrypt(ct); 110 | res_highest_bid_amount = 111 | res_highest_bid_amount + ((bit as u64) << (BID_BITS - 1 - index)); 112 | }); 113 | 114 | // find returned winner id 115 | let mut res_highest_bidder_identity = vec![]; 116 | winner_identity_bit 117 | .iter() 118 | .enumerate() 119 | .for_each(|(index, bit_ct)| { 120 | let bit = client_key.decrypt(bit_ct); 121 | if bit { 122 | res_highest_bidder_identity.push(index); 123 | } 124 | }); 125 | 126 | dbg!(expected_highest_bid_amount, res_highest_bid_amount); 127 | dbg!( 128 | &expected_highest_bidder_identity, 129 | &res_highest_bidder_identity 130 | ); 131 | 132 | assert_eq!(*expected_highest_bid_amount, res_highest_bid_amount); 133 | assert_eq!( 134 | expected_highest_bidder_identity, 135 | res_highest_bidder_identity 136 | ); 137 | 138 | Ok(()) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aes" 7 | version = "0.8.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" 10 | dependencies = [ 11 | "cfg-if", 12 | "cipher", 13 | "cpufeatures", 14 | ] 15 | 16 | [[package]] 17 | name = "aligned-vec" 18 | version = "0.5.0" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" 21 | dependencies = [ 22 | "serde", 23 | ] 24 | 25 | [[package]] 26 | name = "autocfg" 27 | version = "1.1.0" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 30 | 31 | [[package]] 32 | name = "bytemuck" 33 | version = "1.14.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" 36 | 37 | [[package]] 38 | name = "cfg-if" 39 | version = "1.0.0" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 42 | 43 | [[package]] 44 | name = "cipher" 45 | version = "0.4.4" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 48 | dependencies = [ 49 | "crypto-common", 50 | "inout", 51 | ] 52 | 53 | [[package]] 54 | name = "concrete-csprng" 55 | version = "0.4.0" 56 | source = "git+https://github.com/Janmajayamall/tfhe-rs.git#a706afb26ec6a0876d267a4fd793100b75dff4e3" 57 | dependencies = [ 58 | "aes", 59 | "libc", 60 | "rayon", 61 | ] 62 | 63 | [[package]] 64 | name = "concrete-fft" 65 | version = "0.3.0" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "cdb823cf0c7a83ac8f7e38bcda73d754fb8f57797f342cdd7c20a61a1db8b058" 68 | dependencies = [ 69 | "aligned-vec", 70 | "bytemuck", 71 | "dyn-stack", 72 | "num-complex", 73 | "pulp 0.11.11", 74 | "serde", 75 | ] 76 | 77 | [[package]] 78 | name = "cpufeatures" 79 | version = "0.2.11" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" 82 | dependencies = [ 83 | "libc", 84 | ] 85 | 86 | [[package]] 87 | name = "crossbeam-deque" 88 | version = "0.8.3" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" 91 | dependencies = [ 92 | "cfg-if", 93 | "crossbeam-epoch", 94 | "crossbeam-utils", 95 | ] 96 | 97 | [[package]] 98 | name = "crossbeam-epoch" 99 | version = "0.9.15" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" 102 | dependencies = [ 103 | "autocfg", 104 | "cfg-if", 105 | "crossbeam-utils", 106 | "memoffset", 107 | "scopeguard", 108 | ] 109 | 110 | [[package]] 111 | name = "crossbeam-utils" 112 | version = "0.8.16" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 115 | dependencies = [ 116 | "cfg-if", 117 | ] 118 | 119 | [[package]] 120 | name = "crypto-common" 121 | version = "0.1.6" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 124 | dependencies = [ 125 | "generic-array", 126 | "typenum", 127 | ] 128 | 129 | [[package]] 130 | name = "dyn-stack" 131 | version = "0.9.1" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "7fe7f8d7bcc523381d3c437b82cf74805de3931de0da69309ae0fe1bdf7a256e" 134 | dependencies = [ 135 | "bytemuck", 136 | "reborrow", 137 | ] 138 | 139 | [[package]] 140 | name = "either" 141 | version = "1.9.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 144 | 145 | [[package]] 146 | name = "fhe-auctions" 147 | version = "0.1.0" 148 | dependencies = [ 149 | "rand", 150 | "tfhe", 151 | ] 152 | 153 | [[package]] 154 | name = "generic-array" 155 | version = "0.14.7" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 158 | dependencies = [ 159 | "typenum", 160 | "version_check", 161 | ] 162 | 163 | [[package]] 164 | name = "getrandom" 165 | version = "0.2.10" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 168 | dependencies = [ 169 | "cfg-if", 170 | "libc", 171 | "wasi", 172 | ] 173 | 174 | [[package]] 175 | name = "inout" 176 | version = "0.1.3" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 179 | dependencies = [ 180 | "generic-array", 181 | ] 182 | 183 | [[package]] 184 | name = "itertools" 185 | version = "0.11.0" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" 188 | dependencies = [ 189 | "either", 190 | ] 191 | 192 | [[package]] 193 | name = "lazy_static" 194 | version = "1.4.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 197 | 198 | [[package]] 199 | name = "libc" 200 | version = "0.2.149" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" 203 | 204 | [[package]] 205 | name = "memoffset" 206 | version = "0.9.0" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" 209 | dependencies = [ 210 | "autocfg", 211 | ] 212 | 213 | [[package]] 214 | name = "num-complex" 215 | version = "0.4.4" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" 218 | dependencies = [ 219 | "bytemuck", 220 | "num-traits", 221 | "serde", 222 | ] 223 | 224 | [[package]] 225 | name = "num-traits" 226 | version = "0.2.17" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" 229 | dependencies = [ 230 | "autocfg", 231 | ] 232 | 233 | [[package]] 234 | name = "paste" 235 | version = "1.0.14" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 238 | 239 | [[package]] 240 | name = "ppv-lite86" 241 | version = "0.2.17" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 244 | 245 | [[package]] 246 | name = "proc-macro2" 247 | version = "1.0.69" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" 250 | dependencies = [ 251 | "unicode-ident", 252 | ] 253 | 254 | [[package]] 255 | name = "pulp" 256 | version = "0.11.11" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "866e8018d6397b0717100dd4a7948fc8cbc8c4b8ce3e39e98a0e1e878d3ba925" 259 | dependencies = [ 260 | "bytemuck", 261 | ] 262 | 263 | [[package]] 264 | name = "pulp" 265 | version = "0.13.2" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "50ff10f8f3224a1cab64371fbab0fff9b9cb5892076eb9032dc825c2e50894e4" 268 | dependencies = [ 269 | "bytemuck", 270 | "num-complex", 271 | ] 272 | 273 | [[package]] 274 | name = "quote" 275 | version = "1.0.33" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 278 | dependencies = [ 279 | "proc-macro2", 280 | ] 281 | 282 | [[package]] 283 | name = "rand" 284 | version = "0.8.5" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 287 | dependencies = [ 288 | "libc", 289 | "rand_chacha", 290 | "rand_core", 291 | ] 292 | 293 | [[package]] 294 | name = "rand_chacha" 295 | version = "0.3.1" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 298 | dependencies = [ 299 | "ppv-lite86", 300 | "rand_core", 301 | ] 302 | 303 | [[package]] 304 | name = "rand_core" 305 | version = "0.6.4" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 308 | dependencies = [ 309 | "getrandom", 310 | ] 311 | 312 | [[package]] 313 | name = "rayon" 314 | version = "1.8.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" 317 | dependencies = [ 318 | "either", 319 | "rayon-core", 320 | ] 321 | 322 | [[package]] 323 | name = "rayon-core" 324 | version = "1.12.0" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" 327 | dependencies = [ 328 | "crossbeam-deque", 329 | "crossbeam-utils", 330 | ] 331 | 332 | [[package]] 333 | name = "reborrow" 334 | version = "0.5.5" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" 337 | 338 | [[package]] 339 | name = "scopeguard" 340 | version = "1.2.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 343 | 344 | [[package]] 345 | name = "serde" 346 | version = "1.0.190" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" 349 | dependencies = [ 350 | "serde_derive", 351 | ] 352 | 353 | [[package]] 354 | name = "serde_derive" 355 | version = "1.0.190" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" 358 | dependencies = [ 359 | "proc-macro2", 360 | "quote", 361 | "syn", 362 | ] 363 | 364 | [[package]] 365 | name = "syn" 366 | version = "2.0.38" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" 369 | dependencies = [ 370 | "proc-macro2", 371 | "quote", 372 | "unicode-ident", 373 | ] 374 | 375 | [[package]] 376 | name = "tfhe" 377 | version = "0.4.0" 378 | source = "git+https://github.com/Janmajayamall/tfhe-rs.git#a706afb26ec6a0876d267a4fd793100b75dff4e3" 379 | dependencies = [ 380 | "aligned-vec", 381 | "bytemuck", 382 | "concrete-csprng", 383 | "concrete-fft", 384 | "dyn-stack", 385 | "itertools", 386 | "lazy_static", 387 | "paste", 388 | "pulp 0.13.2", 389 | "rayon", 390 | "serde", 391 | ] 392 | 393 | [[package]] 394 | name = "typenum" 395 | version = "1.17.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 398 | 399 | [[package]] 400 | name = "unicode-ident" 401 | version = "1.0.12" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 404 | 405 | [[package]] 406 | name = "version_check" 407 | version = "0.9.4" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 410 | 411 | [[package]] 412 | name = "wasi" 413 | version = "0.11.0+wasi-snapshot-preview1" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 416 | --------------------------------------------------------------------------------