From d9f4afde0ada065d69b301117fdf19d1efb0fd24 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Fri, 26 Jul 2024 15:42:31 +0100 Subject: [PATCH 1/8] separate docker initialisation --- .env.example.admin | 3 + .env.example.node | 3 + README.md | 276 +++++++++++++--------- bin/client.rs | 103 ++++---- contracts/Halo2VerifyingKey-3-5-18-g2.sol | 138 +++++------ docker-compose.yml | 74 +++++- entrypoint.sh | 35 +++ ops/docker/Dockerfile.admin | 10 +- ops/docker/Dockerfile.init | 34 +++ ops/docker/Dockerfile.node | 15 +- services/admin.ts | 36 ++- services/exec/run.ts | 8 + services/exec/runNode.ts | 8 + services/node.ts | 25 ++ 14 files changed, 511 insertions(+), 257 deletions(-) create mode 100644 entrypoint.sh create mode 100644 ops/docker/Dockerfile.init diff --git a/.env.example.admin b/.env.example.admin index 8b36830..dd97470 100644 --- a/.env.example.admin +++ b/.env.example.admin @@ -1,6 +1,9 @@ L2_NODE_WEB3_URL= #interval of service refreshing (in milliseconds); default = 12000 POLLING_INTERVAL= +THRESHOLD=3 +NUMBER_OF_MEMBERS=5 +DEGREE=18 #interval of randomness generation (in seconds); default = 3600 RAND_GEN_INTERVAL= # UTC time for starting producing randoms, e.g., 2024-07-18T12:00:00Z diff --git a/.env.example.node b/.env.example.node index e938830..0214b94 100644 --- a/.env.example.node +++ b/.env.example.node @@ -1,5 +1,8 @@ L2_NODE_WEB3_URL= #interval of service refreshing (in milliseconds); default = 12000 POLLING_INTERVAL= +THRESHOLD=3 +NUMBER_OF_MEMBERS=5 +DEGREE=18 ZK_RAND_ADDRESS= NODE_PRIVATE_KEY= \ No newline at end of file diff --git a/README.md b/README.md index 700aeac..7773351 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # zkRand -zkRand is a t-out-of-n threshold scheme that runs among a group of n distributed members. The protocol consists of two components: -a snark-based non-interactive distributed key generation (NI-DKG) and randomness generation based on threshold bls-signatures. +zkRand is a t-out-of-n threshold scheme that runs among a group of n distributed members. The protocol consists of two +components: +a snark-based non-interactive distributed key generation (NI-DKG) and randomness generation based on threshold +bls-signatures. ### To build: @@ -10,67 +12,70 @@ $ cargo build --release ``` For help information + ``` $ ./target/release/client -h ``` ### Protocol steps -1. Download KZG parameters using: + +1. Download KZG parameters using: ``` sh download_params.sh ``` - This downloads KZG parameters with degree = 22 from Ethereum Powers of Tau. - The parameters are saved in "./kzg_params/params22". This is the KZG ceremony. + This downloads KZG parameters with degree = 22 from Ethereum Powers of Tau. + The parameters are saved in "./kzg_params/params22". This is the KZG ceremony. -2. Config. This step initialises the protocol configuration. -The default config is set to be (threshold, number_of_memnbers, degree) = (3, 5, 18). -This can be changed by: +2. Config. This step initialises the protocol configuration. + The default config is set to be (threshold, number_of_memnbers, degree) = (3, 5, 18). + This can be changed by: ``` $ RUST_LOG=info ./target/release/client config ``` - The configuration is saved at "data/config.toml". The degree determines maximum number of gates allowed in a DNI-KG circuit. - Higher degree is required for supporting more members in the NI-DKG protocol. - The maximun (threshold, number_of_members) that can be supported for a given degree is: - - | degree | 18 | 19 | 20 | 21 | 22 | - |:------:|:------:| :----: | :----: | :----: | :----: | - | (t, n) | (3, 5) | (9, 16) | (20, 38) | (42, 83) | (86, 171) - - The threshold is set as the majority of number_of_members. + The configuration is saved at "data/config.toml". The degree determines maximum number of gates allowed in a DNI-KG + circuit. + Higher degree is required for supporting more members in the NI-DKG protocol. + The maximun (threshold, number_of_members) that can be supported for a given degree is: + + | degree | 18 | 19 | 20 | 21 | 22 | + |:------:|:------:| :----: | :----: | :----: | :----: | + | (t, n) | (3, 5) | (9, 16) | (20, 38) | (42, 83) | (86, 171) + + The threshold is set as the majority of number_of_members. 3. Setup. This generates SNARK proving key and verifying key for NI-DKG circuits, - and the verification contracts for checking SNARK proofs onchain. - The SNARK parameters are generated using: + and the verification contracts for checking SNARK proofs onchain. + The SNARK parameters are generated using: ``` - $ RUST_LOG=info ./target/release/client setup -s + $ RUST_LOG=info ./target/release/client setup --split ``` - The parameters are computed using Ethereum power-of-tau, - therefore, the proving/verifying keys are deterministic given a configuration. - The parameters are stored in "./kzg_params" and the generated contracts in "./contracts". - The option `-s` splits the verifier contract and verifying key contract so that the verifier contract - stays the same for different (t,n) values. The verifying key contract needs to be changed when (t,n) changes. - The current implementation of contracts set (t,n) to be (3, 5). - -4. KeyGen. Before the NI-DKG protocol starts, each member $i$ pre-generates its member public key $mpk_i$ and -secret key $msk_i$ for encryption and decryption in NI-DKG protocol: + The parameters are computed using Ethereum power-of-tau, + therefore, the proving/verifying keys are deterministic given a configuration. + The parameters are stored in "./kzg_params" and the generated contracts in "./contracts". + The option `-s` splits the verifier contract and verifying key contract so that the verifier contract + stays the same for different (t,n) values. The verifying key contract needs to be changed when (t,n) changes. + The current implementation of contracts set (t,n) to be (3, 5). + +4. KeyGen. Before the NI-DKG protocol starts, each member $i$ pre-generates its member public key $mpk_i$ and + secret key $msk_i$ for encryption and decryption in NI-DKG protocol: ``` $ RUST_LOG=info ./target/release/client keygen ``` - The secret key is saved at "./data/members/member.json". The public key is printed in the format: + The secret key is saved at "./data/members/member.json". The public key is printed in the format: ``` { "x":"0x0779273a75396c1c8c874a1b08c8beacf56f0a576142c7251c0be0408554b717", "y":"0x2c3c22206625d7c76d319245dcaa5cadfad9d197933966b73def60f67eccbd36" } ``` - A public key is a point on Grumpkin curve. (x,y) are the point's coordinates - which are 256-bit integers and are encoded as hex string. - Each member submits its member public key to contract "zkdvrf.sol" through - function `registerNode`. The hex string may need to be converted to big integers before submitting to the contract. - In the contract, all the submitted public keys are stored in `pubKeys` and their order is stored in `ppListOrder`. - To use these public keys in the following NI-DKG steps, `pubKeys` should be converted to a list that is compatible - with the Rust backend: - + A public key is a point on Grumpkin curve. (x,y) are the point's coordinates + which are 256-bit integers and are encoded as hex string. + Each member submits its member public key to contract "zkdvrf.sol" through + function `registerNode`. The hex string may need to be converted to big integers before submitting to the contract. + In the contract, all the submitted public keys are stored in `pubKeys` and their order is stored in `ppListOrder`. + To use these public keys in the following NI-DKG steps, `pubKeys` should be converted to a list that is compatible + with the Rust backend: + ``` [ {"x1": "...", "y1": "..."}, @@ -79,58 +84,71 @@ secret key $msk_i$ for encryption and decryption in NI-DKG protocol: {"x5": "...", "y5": "..."}, ] ``` - - The order follows the order in `ppListOrder` and every member must use the same order. - Otherwise the SNARK proof verification won't pass. The converted public keys should be saved at "./data/mpks.json" - for the next steps. - - -5. NI-DKG. - 1. Create public parameters. Each member $i$ selects a random polynomial to create its public parameters $pp_i$ - and a SNARK proof $zkp_i$ to ensure the parameters are generated correctly. - ``` - $ RUST_LOG=info ./target/release/client dkg prove - ``` - Index is the member's position in the list of member public keys. The index ranges 1, 2, ..., number_of_members. - This command reads "./data/mpks.json" to obtain all members public keys. - The public keys are used for encrypting the secret shares each member created for other members. - This command outputs $(pp_i, zkp_i)$ where $pp_i$ is encoded as instance and saved at "./data/dkg/proofs/instance_{INDEX}.json" and - $zkp_i$ is saved at "./data/dkg/proofs/proof_{INDEX}.dat". - $(pp_i, zpk_i)$ can be submitted to the contract `zkdvrf.sol` through function `submitPublicParams` for onchain verification. - $pp_i$ is a list of hex string and needs to be converted to be a list of big integers before sending to the contract. - $zkp_i$ is bytes and can be directly sent to the contract. - - $(pp_i, zpk_i)$ can also be verified locally using - ``` - $ RUST_LOG=info ./target/release/client dkg verify - ``` - This command reads $pp_i$ from "./data/dkg/proofs/instance_{INDEX}.json" - and $zkp_i$ from "./data/dkg/proofs/proof_{INDEX}.dat". - - The current implementation of contracts expect submission from each member. However, - it is in fact not necessary to require each member to generate and submit $pp_i$. - Instead, a lower bound $m$ with threshold < m <= number_of_members can be set to accept the NI-DKG process. - For example, m = (2/3) * number_of_members. If at least m members submit valid $(pp_i, zkp_i)$, then the NI-DKG can be considered successfully. - The members that do not submit will still be able to obtain a secret/verification key pair (in the following steps) as long as their member public keys are included. - These members can be allowed or banned from participating in the randomness generation process. - 3. Derive secret shares and global public parameters. `ppList` in the contract contains - all the submitted public parameters from which each member can derive their secret shares and global public parameters. - Member $i$ can derive its secret share $sk_i$ and the global public parameters using: - - ``` - $ RUST_LOG=info ./target/release/client dkg derive -f - ``` - This command requires member $i$'s secret key $msk_i$ in "./data/members/FILE.json" and all the - public parameters in "./data/all_instances.json". The default value of FILE is "member". `ppList` in the contract is of type `uint256[][]`. - `all_instances.json` is obtained from `ppList` by converting all the uint256 into hex string. From this command, member $i$ - obtains its secret share saved at "./data/dkg/shares/share_{INDEX}.json", a global public key $gpk$ saved at "./data/gpk.json" - and all the verification keys saved at "./data/vks.json". Every member can obtain a verification key regardless of whether the - member participates in the NI-DKG or not. The verification keys are listed in the same order as the member public keys. - The verification key $vk_i$ will be used to verify the partial evaluation generation by member $i$ using its secret share $sk_i$. - -6. Randomness generation: given an unique public string $x$, members jointly generate a pseudorandom value. -This pseudorandom is deterministic which means only one value can pass the pseudorandom verification `verifyPseudoRand` given $gpk$ and $x$. - 1. Each member $i$ computes a partial evaluation $eval_i$ using: + + The order follows the order in `ppListOrder` and every member must use the same order. + Otherwise the SNARK proof verification won't pass. The converted public keys should be saved at "./data/mpks.json" + for the next steps. + + +5. NI-DKG. + 1. Create public parameters. Each member $i$ selects a random polynomial to create its public parameters $pp_i$ + and a SNARK proof $zkp_i$ to ensure the parameters are generated correctly. + ``` + $ RUST_LOG=info ./target/release/client dkg prove + ``` + Index is the member's position in the list of member public keys. The index ranges 1, 2, ..., number_of_members. + This command reads "./data/mpks.json" to obtain all members public keys. + The public keys are used for encrypting the secret shares each member created for other members. + This command outputs $(pp_i, zkp_i)$ where $pp_i$ is encoded as instance and saved at " + ./data/dkg/proofs/instance_{INDEX}.json" and + $zkp_i$ is saved at "./data/dkg/proofs/proof_{INDEX}.dat". + $(pp_i, zpk_i)$ can be submitted to the contract `zkdvrf.sol` through function `submitPublicParams` for onchain + verification. + $pp_i$ is a list of hex string and needs to be converted to be a list of big integers before sending to the + contract. + $zkp_i$ is bytes and can be directly sent to the contract. + + $(pp_i, zpk_i)$ can also be verified locally using + ``` + $ RUST_LOG=info ./target/release/client dkg verify + ``` + This command reads $pp_i$ from "./data/dkg/proofs/instance_{INDEX}.json" + and $zkp_i$ from "./data/dkg/proofs/proof_{INDEX}.dat". + + The current implementation of contracts expect submission from each member. However, + it is in fact not necessary to require each member to generate and submit $pp_i$. + Instead, a lower bound $m$ with threshold < m <= number_of_members can be set to accept the NI-DKG process. + For example, m = (2/3) * number_of_members. If at least m members submit valid $(pp_i, zkp_i)$, then the NI-DKG + can be considered successfully. + The members that do not submit will still be able to obtain a secret/verification key pair (in the following + steps) as long as their member public keys are included. + These members can be allowed or banned from participating in the randomness generation process. + 3. Derive secret shares and global public parameters. `ppList` in the contract contains + all the submitted public parameters from which each member can derive their secret shares and global public + parameters. + Member $i$ can derive its secret share $sk_i$ and the global public parameters using: + + ``` + $ RUST_LOG=info ./target/release/client dkg derive -f + ``` + This command requires member $i$'s secret key $msk_i$ in "./data/members/FILE.json" and all the + public parameters in "./data/all_instances.json". The default value of FILE is "member". `ppList` in the contract + is of type `uint256[][]`. + `all_instances.json` is obtained from `ppList` by converting all the uint256 into hex string. From this command, + member $i$ + obtains its secret share saved at "./data/dkg/shares/share_{INDEX}.json", a global public key $gpk$ saved at " + ./data/gpk.json" + and all the verification keys saved at "./data/vks.json". Every member can obtain a verification key regardless + of whether the + member participates in the NI-DKG or not. The verification keys are listed in the same order as the member public + keys. + The verification key $vk_i$ will be used to verify the partial evaluation generation by member $i$ using its + secret share $sk_i$. + +6. Randomness generation: given an unique public string $x$, members jointly generate a pseudorandom value. + This pseudorandom is deterministic which means only one value can pass the pseudorandom verification + `verifyPseudoRand` given $gpk$ and $x$. + 1. Each member $i$ computes a partial evaluation $eval_i$ using: ``` $ RUST_LOG=info ./target/release/client rand eval ``` @@ -138,7 +156,7 @@ This pseudorandom is deterministic which means only one value can pass the pseud The output of $eval_i$ is saved at "./data/random/eval_{INDEX}.json". The validity of $eval_i$ can be checked against member $i$'s verification key $vk_i$. $eval_i$ can be submitted to the contract `zkdvrf.sol` through function `submitPartialEval`. - An example of $eval_i$ is + An example of $eval_i$ is ``` { "index":1, @@ -153,16 +171,19 @@ This pseudorandom is deterministic which means only one value can pass the pseud ``` This command reads $eval_i$ from "./data/random/eval_{INDEX}.json" and verification keys from "./data/vks.json". - 2. Once there are at least $t$ valid partial evaluations, a combiner can combine these partial evaluations into the final pseudorandom value and generates a proof to show the value is correct. - The combination process can be performed by any party and it doesn't involve any secret information. To save the onchain verification cost, the combination can be done offchain and - only the final pseudorandom value and its proof needs to be verified onchain. + 2. Once there are at least $t$ valid partial evaluations, a combiner can combine these partial evaluations into the + final pseudorandom value and generates a proof to show the value is correct. + The combination process can be performed by any party and it doesn't involve any secret information. To save the + onchain verification cost, the combination can be done offchain and + only the final pseudorandom value and its proof needs to be verified onchain. ``` $ RUST_LOG=info ./target/release/client rand combine ``` - This command reads all partial evaluations from "./data/evals.json" - and outputs a pseudorandom value saved at "./data/random/pseudo.json". - In the contract, all the submitted partial evaluations are stored in `roundToEval` -which can be used to obtain "evals.json" by converting all the big integers into hex string and changing the map 'roundToEval' to a list of mapped values such as + This command reads all partial evaluations from "./data/evals.json" + and outputs a pseudorandom value saved at "./data/random/pseudo.json". + In the contract, all the submitted partial evaluations are stored in `roundToEval` + which can be used to obtain "evals.json" by converting all the big integers into hex string and changing the map ' + roundToEval' to a list of mapped values such as ``` [ {"index":1,"value":{"x":"...","y":"..."},"proof":{"z":"...","c":"..."}}, @@ -172,22 +193,24 @@ which can be used to obtain "evals.json" by converting all the big integers into {"index":5,"value":{"x":"...","y":"..."},"proof":{"z":"...","c":"..."}} ] ``` - Partial evaluations contain indices, so they do not need to be sorted. The indices are used in the combination algorithm. - The final pseudorandom value has the format: + Partial evaluations contain indices, so they do not need to be sorted. The indices are used in the combination + algorithm. + The final pseudorandom value has the format: ``` { "proof":{"x":"0x2028e15050ef4550f0530afad37dfc8928566dbbd31edbe7f244afe3cb0d1c3f","y":"0x0e7b0ecb46b03fb589eedf8136b451f6171b01ce903156768be9e511878df08f"}, "value":[51,167,113,177,40,238,25,153,158,212,223,21,117,190,95,162,86,65,154,24,164,217,242,200,239,74,162,60,122,208,48,0] } ``` - It can be submitted to the contract through `submitRandom` for onchain verification and storage. The pseudorandom value is "value" which is the 32-bytes keccak hash of "proof". - The hex string in "proof" may need to be converted to big integers before submitting. - - The pseudorandom value can also be verified locally: + It can be submitted to the contract through `submitRandom` for onchain verification and storage. The pseudorandom + value is "value" which is the 32-bytes keccak hash of "proof". + The hex string in "proof" may need to be converted to big integers before submitting. + + The pseudorandom value can also be verified locally: ``` $ RUST_LOG=info ./target/release/client rand verify-final ``` - This command reads pseudorandom from "./data/random/pseudo.json". + This command reads pseudorandom from "./data/random/pseudo.json". ## Deploy @@ -205,11 +228,13 @@ GPP = # optional PSRAND = # optional ``` -deploying the helpers are optional, and to proceed with using prior-deployed helpers, set `DEPLOY_NO_HELPERS` to true and supply the `HALO2V`, `GPP`, `PSRAND` contract addresses. +deploying the helpers are optional, and to proceed with using prior-deployed helpers, set `DEPLOY_NO_HELPERS` to true +and supply the `HALO2V`, `GPP`, `PSRAND` contract addresses. If you are unsure, do not set the optional params. 2. Run the deploy script with + ``` $ yarn deploy ``` @@ -217,17 +242,19 @@ $ yarn deploy ## Running Tests Run contract tests using- + ``` $ yarn test ``` ## Running the Demo -The Demo offers a quick, interactive overview of the system's end-to-end flow, including memeber interactions, the different phases and their functionality. +The Demo offers a quick, interactive overview of the system's end-to-end flow, including memeber interactions, the +different phases and their functionality. ### Step-1: Build -1. Build by running +1. Build by running ``` $ cargo build --release @@ -239,13 +266,15 @@ $ cargo build --release sh download_params.sh ``` -3. Setup proving key and verifying key. This might take a few minutes. This command also generates SNARK verifier contract. +3. Setup proving key and verifying key. This might take a few minutes. This command also generates SNARK verifier + contract. ``` -RUST_LOG=info ./target/release/client setup -s +RUST_LOG=info ./target/release/client setup --split ``` -4. The demo will require a test blockchain, for a quickstart - download [Ganache](https://archive.trufflesuite.com/ganache/) and start a local network +4. The demo will require a test blockchain, for a quickstart - + download [Ganache](https://archive.trufflesuite.com/ganache/) and start a local network ``` ganache --wallet.seed "my insecure seeds" @@ -292,23 +321,28 @@ yarn member ### Step-4: Generating Random -1. After the NIDKG process is complete, the admin script will automatically initiate a round for random generation. Follow the instructions on the admin window and run the following for the members to submit partial evaluations- +1. After the NIDKG process is complete, the admin script will automatically initiate a round for random generation. + Follow the instructions on the admin window and run the following for the members to submit partial evaluations- ``` yarn random ``` -After the members have done submitting partial evaluations - verify that a pseudorandom number is generated on the admin window! -Respond 'yes' on the admin window to start producing the next pseudorandom and 'no' to quit. +After the members have done submitting partial evaluations - verify that a pseudorandom number is generated on the admin +window! +Respond 'yes' on the admin window to start producing the next pseudorandom and 'no' to quit. ### Re-running -If you have exited the admin script, but have already been through the NIDKG process, you can continue with random number generation through running- + +If you have exited the admin script, but have already been through the NIDKG process, you can continue with random +number generation through running- ``` yarn admin:restart ``` ### Continuing with lottery demo + 1. Deploy the lottery contracts ``` @@ -321,16 +355,22 @@ a) your lottery.sol deployed address b) private keys for lottery admin and three players from ganache pre-generated accounts 3. Run the lottery admin to start the lottery + ``` yarn lottery:admin ``` -The lottery will set a target random for picking up a winner. + +The lottery will set a target random for picking up a winner. The round number for target random is set to be 3 in the script. 4. Run the players to place bets + ``` yarn lottery:play ``` -Before Zkdvrf starts producing the target random, players can enter the lottery by depositing a certain amount of ethers. -5. Continuing the above Step-4 for generating random until the round number hits 3 which will trigger the lottery admin to pick and pay a winner. \ No newline at end of file +Before Zkdvrf starts producing the target random, players can enter the lottery by depositing a certain amount of +ethers. + +5. Continuing the above Step-4 for generating random until the round number hits 3 which will trigger the lottery admin + to pick and pay a winner. \ No newline at end of file diff --git a/bin/client.rs b/bin/client.rs index ca4c6cf..524c5bc 100644 --- a/bin/client.rs +++ b/bin/client.rs @@ -72,8 +72,11 @@ enum Commands { Mock(MockArgs), /// Generate kzg parameters, proving key and verifying key for SNARKs and verifier contract Setup { + /// If skip is selected, it skips the contract generation + #[arg(long, default_value_t = false)] + skip: bool, /// If split is selected, verifier contract and verifying key contract are generated separately - #[arg(short, long, default_value_t = false)] + #[arg(long, default_value_t = false)] split: bool, }, /// Generate member secret/public key pair @@ -260,7 +263,7 @@ fn public_keys(dkg_config: &DkgConfig, instance: &[BnScalar]) -> Vec { pks } -fn setup(params: &ParamsConfig, split: bool) -> Result<()> { +fn setup(params: &ParamsConfig, skip: bool, split: bool) -> Result<()> { let start = start_timer!(|| format!("kzg load or setup params with degree {}", params.degree)); let general_params = load_or_create_params(KZG_PARAMS_DIR, params.degree as usize)?; end_timer!(start); @@ -280,52 +283,54 @@ fn setup(params: &ParamsConfig, split: bool) -> Result<()> { let vk = pk.get_vk(); end_timer!(start); - let num_instances = dkg_config.instance_size(); - - if split { - let start = start_timer!(|| format!( - "create verifier contract and verifying key contract for ({}, {}, {})", - params.threshold, params.number_of_members, params.degree - )); - let generator = SolidityGenerator::new(&general_params, vk, Bdfg21, num_instances); - let (verifier_solidity, vk_solidity) = generator.render_separately().unwrap(); - save_solidity("Halo2Verifier.sol", &verifier_solidity)?; - - let contract_name = if cfg!(feature = "g2chip") { - format!( - "Halo2VerifyingKey-{}-{}-{}-g2.sol", - params.threshold, params.number_of_members, params.degree, - ) + if !skip { + let num_instances = dkg_config.instance_size(); + + if split { + let start = start_timer!(|| format!( + "create verifier contract and verifying key contract for ({}, {}, {})", + params.threshold, params.number_of_members, params.degree + )); + let generator = SolidityGenerator::new(&general_params, vk, Bdfg21, num_instances); + let (verifier_solidity, vk_solidity) = generator.render_separately().unwrap(); + save_solidity("Halo2Verifier.sol", &verifier_solidity)?; + + let contract_name = if cfg!(feature = "g2chip") { + format!( + "Halo2VerifyingKey-{}-{}-{}-g2.sol", + params.threshold, params.number_of_members, params.degree, + ) + } else { + format!( + "Halo2VerifyingKey-{}-{}-{}.sol", + params.threshold, params.number_of_members, params.degree, + ) + }; + + save_solidity(contract_name, &vk_solidity)?; + end_timer!(start); } else { - format!( - "Halo2VerifyingKey-{}-{}-{}.sol", - params.threshold, params.number_of_members, params.degree, - ) - }; - - save_solidity(contract_name, &vk_solidity)?; - end_timer!(start); - } else { - let start = start_timer!(|| format!( - "create solidity contracts for ({},{},{})", - params.threshold, params.number_of_members, params.degree - )); - let generator = SolidityGenerator::new(&general_params, vk, Bdfg21, num_instances); - let verifier_solidity = generator.render()?; - let contract_name = if cfg!(feature = "g2chip") { - format!( - "Halo2Verifier-{}-{}-{}-g2.sol", - params.threshold, params.number_of_members, params.degree, - ) - } else { - format!( - "Halo2Verifier-{}-{}-{}.sol", - params.threshold, params.number_of_members, params.degree, - ) - }; - - save_solidity(contract_name, &verifier_solidity)?; - end_timer!(start); + let start = start_timer!(|| format!( + "create solidity contracts for ({},{},{})", + params.threshold, params.number_of_members, params.degree + )); + let generator = SolidityGenerator::new(&general_params, vk, Bdfg21, num_instances); + let verifier_solidity = generator.render()?; + let contract_name = if cfg!(feature = "g2chip") { + format!( + "Halo2Verifier-{}-{}-{}-g2.sol", + params.threshold, params.number_of_members, params.degree, + ) + } else { + format!( + "Halo2Verifier-{}-{}-{}.sol", + params.threshold, params.number_of_members, params.degree, + ) + }; + + save_solidity(contract_name, &verifier_solidity)?; + end_timer!(start); + } } Ok(()) @@ -387,8 +392,8 @@ fn main() -> Result<()> { ); } } - Commands::Setup { split } => { - setup(¶ms, split)?; + Commands::Setup { skip, split } => { + setup(¶ms, skip, split)?; } Commands::Keygen { file } => { let member = MemberKey::random(&mut rng); diff --git a/contracts/Halo2VerifyingKey-3-5-18-g2.sol b/contracts/Halo2VerifyingKey-3-5-18-g2.sol index 721db5a..d5973bf 100644 --- a/contracts/Halo2VerifyingKey-3-5-18-g2.sol +++ b/contracts/Halo2VerifyingKey-3-5-18-g2.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; contract Halo2VerifyingKey { constructor() { assembly { - mstore(0x0000, 0x28f484b8e38cdbda30a10af8ebbb41e5e707105e86f1a0f965f61865847076d6) // vk_digest + mstore(0x0000, 0x02f3c36a5a29edffed73563df762e43806a2459d7ba723ff3ed99c7305a1aa47) // vk_digest mstore(0x0020, 0x0000000000000000000000000000000000000000000000000000000000000031) // num_instances mstore(0x0040, 0x0000000000000000000000000000000000000000000000000000000000000012) // k mstore(0x0060, 0x30644259cd94e7dd5045d7a27013b7fcd21c9e3b7fa75222e7bda49b729b0401) // n_inv @@ -22,74 +22,74 @@ contract Halo2VerifyingKey { mstore(0x01c0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) // g2_x_2 mstore(0x01e0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) // g2_y_1 mstore(0x0200, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) // g2_y_2 - mstore(0x0220, 0x186282957db913abd99f91db59fe69922e95040603ef44c0bd7aa3adeef8f5ac) // neg_s_g2_x_1 - mstore(0x0240, 0x17944351223333f260ddc3b4af45191b856689eda9eab5cbcddbbe570ce860d2) // neg_s_g2_x_2 - mstore(0x0260, 0x06d971ff4a7467c3ec596ed6efc674572e32fd6f52b721f97e35b0b3d3546753) // neg_s_g2_y_1 - mstore(0x0280, 0x06ecdb9f9567f59ed2eee36e1e1d58797fd13cc97fafc2910f5e8a12f202fa9a) // neg_s_g2_y_2 - mstore(0x02a0, 0x05eb072e2e25be4cd57050b2479563a8cab0a33474a26873ae63c927995aa6ae) // fixed_comms[0].x - mstore(0x02c0, 0x2f9b4b6b6255f64ccc8b47e0a2bc12a205428ae623f499fb424f33570845dd36) // fixed_comms[0].y - mstore(0x02e0, 0x189f7e8a01397ea94d60fde3c1d011691522b5346704df4aef2545ef01d08c3b) // fixed_comms[1].x - mstore(0x0300, 0x203196b23e9abf6bbf25739404084c9fbcf74472aa85afb3c2fe0fd663b1beb5) // fixed_comms[1].y - mstore(0x0320, 0x0fa049ad36cdfc60f60e0191a48b4e9f847d5bbb4f23a266d107c91daf4e372d) // fixed_comms[2].x - mstore(0x0340, 0x1639428cf4875e46ba50588b9bbf46ce90e7a427581aef099d784efe05b93cb3) // fixed_comms[2].y - mstore(0x0360, 0x1db0ac7bfaea513a6540a0eb99711d1bb5842656d18d1e6ca6b152d86c683cea) // fixed_comms[3].x - mstore(0x0380, 0x2bf00d4d4000b1d5318f9e6d640bcffb1dd730f42241f563f0be99383a8d4145) // fixed_comms[3].y - mstore(0x03a0, 0x23675493f72c7cb1991b68110ff45c0609dbb75996995a3518c0e8e869606083) // fixed_comms[4].x - mstore(0x03c0, 0x0d9978f391afee252992a7ab050e5c90e3feefe0d25409880a9cbe40bfa0d728) // fixed_comms[4].y - mstore(0x03e0, 0x1b056c80ba2e49492e168276b113067272ae65e00513aad90b8a5a045364aae9) // fixed_comms[5].x - mstore(0x0400, 0x0beb8cc57c02c565ce9645ae3cac718983d03de9a27bb8d1822a5829c591be6c) // fixed_comms[5].y - mstore(0x0420, 0x1eb3a757059c7c2be4d1565e750a53bdac346f2bf3acd1b1d9f3e42d2dfadb3d) // fixed_comms[6].x - mstore(0x0440, 0x172d7b846542f86e0f285fb9d6c9ecdd682746e4ea61c0715d7e91346c71f11d) // fixed_comms[6].y - mstore(0x0460, 0x2df72f0703821c3aba995e0bd010703a389f80a23a2870e817d13dfa1779779a) // fixed_comms[7].x - mstore(0x0480, 0x0d6e18412c38631db01a1e0b2529798a3da672bb238c80a60b9db371a068616e) // fixed_comms[7].y - mstore(0x04a0, 0x143ee6d7d3ac176207e54b9bb293879045e7f06efbeabcdabf178123b81b167c) // fixed_comms[8].x - mstore(0x04c0, 0x0982b69f805c16991ad606fe005cddcd756668993d23dc6939ec3dcfa6edce2d) // fixed_comms[8].y - mstore(0x04e0, 0x081a1d562f38b857fb7e200bb455094a011510db9ac0352f4a01fee1674d134d) // fixed_comms[9].x - mstore(0x0500, 0x19421a4d1ab26b52bd8d1826af0c406339c8a4859e24c56dd25a7d7a72632b40) // fixed_comms[9].y - mstore(0x0520, 0x098055bc990ea7766dbcd9e68cab85424dbc1e35b475b828ac74bad04a0e4993) // fixed_comms[10].x - mstore(0x0540, 0x2dff61482366aedf115b5620ecba51925967fd2b76f882535d3a8440bb9e632e) // fixed_comms[10].y - mstore(0x0560, 0x2016f7f2c8a1037db9ec20e05dac5a3ab01050f50a3027574921074097d82ce6) // fixed_comms[11].x - mstore(0x0580, 0x09db885711903280e326733335e89f86fccee1658e39094fa57592f2d24fb171) // fixed_comms[11].y - mstore(0x05a0, 0x2f35e2101fb85e89e1d759ba971caa126954e293132416689f12f230a40a3bb4) // fixed_comms[12].x - mstore(0x05c0, 0x1209c7e542e7a230dbe20c157baacba7c28fcc0aea9aef328df79a9db677078f) // fixed_comms[12].y - mstore(0x05e0, 0x1af95d0cfad6dc54ccf7f4eee74aa57a58ba0a2e0cc60a215691dfa3879b373c) // fixed_comms[13].x - mstore(0x0600, 0x214d6e7644ce1d2057bd2ad4d1bf86cc126e5c07d366e96f7b9405efa74155e2) // fixed_comms[13].y - mstore(0x0620, 0x2f3a4c970d966e28ee4e4ddc33e2c724e184266eb946f778aa89a385d97d5360) // fixed_comms[14].x - mstore(0x0640, 0x1e3863e0433a4f27be02a700fe3f7505ea9b29f283e370c6f6629dff348d9d02) // fixed_comms[14].y - mstore(0x0660, 0x118e811b4f633ea7348d7bbbf6e5044591c73aa85468b97e09be5e9ecaf0550b) // fixed_comms[15].x - mstore(0x0680, 0x1df89de9194a38a5d2173fd86caaef04c2919c0c9faec2e9fdce03142b861dc7) // fixed_comms[15].y - mstore(0x06a0, 0x12cb83ada9f9120853b59ea7971dba8bd30ce170187575e81ae0743334b269f0) // fixed_comms[16].x - mstore(0x06c0, 0x2f9c5b12fedf34efc451e3ff8344d2e58c66c656a4fb38069af2cc89d6699f09) // fixed_comms[16].y - mstore(0x06e0, 0x1a8c4ebfcba32af38c02e59235886ac12164cd573359b99aaca8c7f6896cf70a) // fixed_comms[17].x - mstore(0x0700, 0x29aec80f63f58bb0faf447e6fc8400a68aeaf3469ba28123523782f2f82bc9d9) // fixed_comms[17].y - mstore(0x0720, 0x042105d74438a95d3e9dfc6d3fef7dcb850478184e38bc23241a06b2e83b0886) // fixed_comms[18].x - mstore(0x0740, 0x18d31e7bca6a9dcf2101086dc68fc0789f5e794064957809f302b4fe5518fd04) // fixed_comms[18].y - mstore(0x0760, 0x0469cf9a28695cf4230e884c3d866b9eebc717da5000d2c0bbfa727e19bfb5bc) // fixed_comms[19].x - mstore(0x0780, 0x28cb90afe58474ae587e422e0f1d1e65e518af567ed3f837258d97f2fd417ed5) // fixed_comms[19].y - mstore(0x07a0, 0x0a74d96d6d81255eacde6623799f50288c7f40635e6b466b73869fd67b7b9c68) // fixed_comms[20].x - mstore(0x07c0, 0x23c98458690ab8999d017f0fa1ccae390013977d9e82e36f9a45bc0b62c181e5) // fixed_comms[20].y - mstore(0x07e0, 0x2b299b627e8ba7e8505ef39eb9f3de3399487f0b501c48af89d0c5384789894f) // fixed_comms[21].x - mstore(0x0800, 0x0aaca08094f1b0f00afae4cd40085a266c5dbfdf028d08d0045a3f0bbd108213) // fixed_comms[21].y - mstore(0x0820, 0x082eee13998b0eab15f47654a2a1dd1f087b4488181ff583aed6e31f09b0d84f) // fixed_comms[22].x - mstore(0x0840, 0x2df0468511a9a9ea67280eb7fd5b13563d6523b0b2cbfed93a1a107c090d0179) // fixed_comms[22].y - mstore(0x0860, 0x107f9b4031048405cf7fe79f479aa7d034ed5ee476bac3d2883d9cf590f32f36) // permutation_comms[0].x - mstore(0x0880, 0x1fd1d5e6962addf04a6c7a41d1f285f74a63e0cdc7ef3d566f924ec65b26c216) // permutation_comms[0].y - mstore(0x08a0, 0x290c6d652d0feebe6e5134951efc8f91f098603db59ccdf1c71790001bf475e9) // permutation_comms[1].x - mstore(0x08c0, 0x04a8c6f2a650e8c1af9271dfce5d4e2c47cf84fa5deab2bbabfc0da1500f7aa5) // permutation_comms[1].y - mstore(0x08e0, 0x20d821cae9011a22b46601119b2850b7cb1e6022d2177b90704d7d0d4824fa9d) // permutation_comms[2].x - mstore(0x0900, 0x1b0dc4704aefde1f077e4291a6e7fefad8f1d68113f17a39561333b094f80828) // permutation_comms[2].y - mstore(0x0920, 0x2dbf71560e208ebfdcafba5948af4daf13eccaa4946e8980355a70f6a88939e5) // permutation_comms[3].x - mstore(0x0940, 0x0a59ab9e6f9e38ece0fcf671e86a100756e9dcebd57e9e248117c396c748f8ac) // permutation_comms[3].y - mstore(0x0960, 0x19176750d0598f78083d4ab19cacd9d04d6adaa8eeef06fd3ab7b79a607c5bfe) // permutation_comms[4].x - mstore(0x0980, 0x05621c33df32e7fabac1205f2e6646b0f647fbe3c36c18c39a8b305909a46e1e) // permutation_comms[4].y - mstore(0x09a0, 0x1b33185590dc0c788bcece4805839c555dae54f38f3f0ce6aa1056fb1156cd7c) // permutation_comms[5].x - mstore(0x09c0, 0x0f5f1df59253d748d42a6810fb47c4100e9ed6179c231d8199f37680626a0183) // permutation_comms[5].y - mstore(0x09e0, 0x0bfac06910eaf9aeca38a84550d36e5432ea90b47060a078e4f98cf608bc566e) // permutation_comms[6].x - mstore(0x0a00, 0x0355eecc37b6bed24f95964c0089a4f3a86669c78ad2b99dd1ac8f19407cfabd) // permutation_comms[6].y - mstore(0x0a20, 0x13ab267051d6a77d28fee208708d3b7e8bb36637e441724a5cb96095ed50187a) // permutation_comms[7].x - mstore(0x0a40, 0x262f5493e2aa9d750f56a70fa203b4658b7c9c058097abc6f205bc05941da0aa) // permutation_comms[7].y - mstore(0x0a60, 0x01a7837e6470babb230978a3079af34e382588caaf1c0c791e81f37222798929) // permutation_comms[8].x - mstore(0x0a80, 0x155c9bea95acf37b018196229c82254163940010ab902b96a4dcde67c6a99a6f) // permutation_comms[8].y + mstore(0x0220, 0x172aa93c41f16e1e04d62ac976a5d945f4be0acab990c6dc19ac4a7cf68bf77b) // neg_s_g2_x_1 + mstore(0x0240, 0x2ae0c8c3a090f7200ff398ee9845bbae8f8c1445ae7b632212775f60a0e21600) // neg_s_g2_x_2 + mstore(0x0260, 0x190fa476a5b352809ed41d7a0d7fe12b8f685e3c12a6d83855dba27aaf469643) // neg_s_g2_y_1 + mstore(0x0280, 0x1c0a500618907df9e4273d5181e31088deb1f05132de037cbfe73888f97f77c9) // neg_s_g2_y_2 + mstore(0x02a0, 0x1571f5c7630c9b40377fdeac6a9bff5aca849775e5c9bfdff28b0d56ab66fade) // fixed_comms[0].x + mstore(0x02c0, 0x04454e034377ce9eada52b79758574a1f6bec4a5d1a9b1000bf4b37dfef9728f) // fixed_comms[0].y + mstore(0x02e0, 0x22860facd1f6e926189502423c2c5a9574a029165785fb4e2d97c54842de79e2) // fixed_comms[1].x + mstore(0x0300, 0x269c82dccd1cc0c1f7d1dde27af2b70bc816d55a85e5d34eda84ac59681fbfc7) // fixed_comms[1].y + mstore(0x0320, 0x11169d533df30955762cebaef67b978dfe93364748b6d3c0f8b5d969009bbea0) // fixed_comms[2].x + mstore(0x0340, 0x05b1ae24179e5f2f6940f75d321a41a32b6daea42f945317afe4ac3fa0aed0ff) // fixed_comms[2].y + mstore(0x0360, 0x10b16e23a89a9c782eb3ac24b339874870f2c28881ad9671f2808ca0ddf85f1a) // fixed_comms[3].x + mstore(0x0380, 0x04284e3800e6694e3f463bba6768fa81edf44a1b43b6b14328c479fc9d0b3dd7) // fixed_comms[3].y + mstore(0x03a0, 0x20cacc43aec4d41d72fd6692234c438dcc616fa1b2a531b509d338a2590134f9) // fixed_comms[4].x + mstore(0x03c0, 0x0b233f76cc566c1ca836d32c1ebecd32cbcd5bae9f6ac940e3b5bf93a3b238f5) // fixed_comms[4].y + mstore(0x03e0, 0x26e82a20748fe704a6eb502be134800d27a51fb6ec86b310daa2302371ef875b) // fixed_comms[5].x + mstore(0x0400, 0x0981fcfe54baac54439ccd0299d93a8e50a235bcf96ed527f23fde221023d544) // fixed_comms[5].y + mstore(0x0420, 0x206497f656d155232b89a1dcdc84f741c8fdf992657ff6668e6003e250525ba2) // fixed_comms[6].x + mstore(0x0440, 0x1ac410f4cf9aac1639f2d6ce154916094594813a8e9b81124b8262ecc3c06329) // fixed_comms[6].y + mstore(0x0460, 0x244b7b52a4be237bbeb91bc1be40326bd38ff6611cc7a87d21e4755dbb27d97a) // fixed_comms[7].x + mstore(0x0480, 0x280a58227ce85bb0465f4f24e0b76289a1529a4fee22428da6e19314ddf3bc81) // fixed_comms[7].y + mstore(0x04a0, 0x16e4e63505df177bacfa1456b0223a7ef3d31daada6f6b6393ce81783c894117) // fixed_comms[8].x + mstore(0x04c0, 0x0720241c0dd6c6d385fb7fb06d96c3625791d560e31f24cb3b8bd4e9166b395b) // fixed_comms[8].y + mstore(0x04e0, 0x1534d762affa5f34b85c0c841a444b2eab2ff9be27abf422c0a067563b61ad8e) // fixed_comms[9].x + mstore(0x0500, 0x097c4118763f9f91fc7fe4d599e15ca1c853634dda944a43ad20fde87e1437d8) // fixed_comms[9].y + mstore(0x0520, 0x06a03d24a14f4c30d9d9bc40538922a71796220be15fb7202c6bb50fc25a54aa) // fixed_comms[10].x + mstore(0x0540, 0x123f19e843116be66fd91d9f7f928eba8e3902282cc6aeed000964df6d907ef9) // fixed_comms[10].y + mstore(0x0560, 0x078d5c66cdaa21420776783334a04be2a75e29bf70668fb608e771ebdab0abee) // fixed_comms[11].x + mstore(0x0580, 0x24b79cf62d3c738630d490fdfd4295083763cc86ffc038bae237e21371318366) // fixed_comms[11].y + mstore(0x05a0, 0x2ed84487ed99478152b46e48924affeb37ccb6feb966876d764c442ccffd7ee4) // fixed_comms[12].x + mstore(0x05c0, 0x28598da0148d15a389da39c32f42aedc5e605524a213c67ba7f7441495af9770) // fixed_comms[12].y + mstore(0x05e0, 0x163f8a58698269e283c0c2b4170d2fe74497526bf8a592d281d772d6c36c99cd) // fixed_comms[13].x + mstore(0x0600, 0x0f4a8b7fe003a579692b534a2d8c218c67006834cafb8f1029f64f986e6ab7ad) // fixed_comms[13].y + mstore(0x0620, 0x0cd536d8fc67ecb3da4cb6db58ff25f68aa55c021cb5aaadbdec798f13f793c4) // fixed_comms[14].x + mstore(0x0640, 0x1f5a77a7784707a5a28c0c4c9432611085cf93ef5d37ba9b395f396dc81f833a) // fixed_comms[14].y + mstore(0x0660, 0x2ac6e14d310b276367d61cf2a4d5d5297e0664b97f21bf8a4958a41051a11842) // fixed_comms[15].x + mstore(0x0680, 0x2670a3c7944956289cfb895083c3a3659784dce1ba581ee657d9a8021b4f5ffb) // fixed_comms[15].y + mstore(0x06a0, 0x1d9009e841c6e5129d052701b76ffd481b3a3bc21ee7a17383106fa5f10f7c03) // fixed_comms[16].x + mstore(0x06c0, 0x2dee49d7e29188dbdf7eed039cf77b0511ab6cc5e611e9e4d3a696d41f9da25c) // fixed_comms[16].y + mstore(0x06e0, 0x010cd824cd8ec841e3e1cceb23fa9cb5f3d227785a3b64531f75d10482bb1cf8) // fixed_comms[17].x + mstore(0x0700, 0x14b812a905aa89e14196b47dc52af6904293822e9a77176af599668813291273) // fixed_comms[17].y + mstore(0x0720, 0x1e9c6118c7e219e8cdfd7594762dd482024bf55c9c1539275ac7780ee94b8418) // fixed_comms[18].x + mstore(0x0740, 0x2dedd8e9074bc0b4413693915077a4d27a48e56dbe4b1f1ecaff5e6b46c4a70f) // fixed_comms[18].y + mstore(0x0760, 0x23ac44d545cdbfcb9d443ef507cad01729b015451088118caa0bd84ab4668d78) // fixed_comms[19].x + mstore(0x0780, 0x1fa9065b8741f55582a68bb3a4d61d57dd530240bbf2c25e9725da038384251f) // fixed_comms[19].y + mstore(0x07a0, 0x0758771c463147b118f3af1a369b2c55741d49db71a41552b7f2871b17b6cbe2) // fixed_comms[20].x + mstore(0x07c0, 0x235e8a8bccb5f289733880f2de5257e8451d2579abedff3cc06c862bfb1d6cef) // fixed_comms[20].y + mstore(0x07e0, 0x015eab43a9f4d71980590c9583325ca562ffcea2890e35420fa12d54f701da8b) // fixed_comms[21].x + mstore(0x0800, 0x2526668d07cb0c169108c09e1ec84e45f2f83c5b741f624e194ef02849f4fd09) // fixed_comms[21].y + mstore(0x0820, 0x01eb56f799af469b397c6110a5950682a636b163542ddabf0be4bb90bdf74b0f) // fixed_comms[22].x + mstore(0x0840, 0x2aabd6b6f8bb5bc4d8bfe2d77e07f2b144bc09b428a9bf6c1aecbb41c9bf2f77) // fixed_comms[22].y + mstore(0x0860, 0x2b0f4175273f10bf767b57c7512bb8f2b4c43d59bccf07bde991d21a69f35913) // permutation_comms[0].x + mstore(0x0880, 0x05816fe8a870114ac4e376c3f6d10d29a804f34b1a4320430534d25cbfc3cde9) // permutation_comms[0].y + mstore(0x08a0, 0x24aa773c2969e17a0a14af06dbf184489eeaadb7b43d82d00fb8a3528771f6af) // permutation_comms[1].x + mstore(0x08c0, 0x02738c2b989544b730655326b560f705aa5b4291de9541a6f17cb3a61736991c) // permutation_comms[1].y + mstore(0x08e0, 0x28184c7a4e97fd82723b7019eca047c6110d4d8b7d70e89fa0d2181620ef11df) // permutation_comms[2].x + mstore(0x0900, 0x283ef06e680a9473ea2b419cccd998b3e69bb119a785fd07305583e4e9cb23de) // permutation_comms[2].y + mstore(0x0920, 0x0873dddca010747e3ea5a4d9f9166de3dacf9a307677e2a5ce2d0c6294c7add8) // permutation_comms[3].x + mstore(0x0940, 0x0347050b6661e055310c145ba744e759d2311c55e6a36327bb9746914b4e54a9) // permutation_comms[3].y + mstore(0x0960, 0x252b866ca945e61d7dc25845bc910600bd4150192e1eafc9ddfb561009bf5b66) // permutation_comms[4].x + mstore(0x0980, 0x04270813f2190ffc50395ece5dc408e81e5542569b81ff50f254d75d8cb14dfb) // permutation_comms[4].y + mstore(0x09a0, 0x0b90b2bd42341870d0e824692904fe9e0f0a1154e3c0d45d973a1c39ac14e91e) // permutation_comms[5].x + mstore(0x09c0, 0x050832d6b790573a4b050f220fcbd0b485d5f05b88fc6005ad6cec372f4f3e9a) // permutation_comms[5].y + mstore(0x09e0, 0x19667763c031ec5db9ceeda538a2f838ef3e86fd55916bc351a448085e79095c) // permutation_comms[6].x + mstore(0x0a00, 0x07d67946527f49e4011475b4ac1ec33f2ee13edbbe68a5cd6b8ea12d22c93538) // permutation_comms[6].y + mstore(0x0a20, 0x05fcc65042dcfe4b5219f973d97a5c47a183c364ada63fa9cd64801df9af4a03) // permutation_comms[7].x + mstore(0x0a40, 0x06b7d26a40848c5a04eb52dc54c826fb34e7e9d57826d454efd213bebf20c994) // permutation_comms[7].y + mstore(0x0a60, 0x2d0907a38fb7970289a839670c23458478994c2e3b6ffcf2bceebb3207d039f3) // permutation_comms[8].x + mstore(0x0a80, 0x0665a7d46d31912dfc39276edff88bf8b8418739c08cd3b2d93a159dce3e1a84) // permutation_comms[8].y return(0, 0x0aa0) } diff --git a/docker-compose.yml b/docker-compose.yml index a0f2b8c..0a1aca0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,33 @@ services: + init: + build: + context: . + dockerfile: ops/docker/Dockerfile.init + volumes: + - kzg_params_volume:/app/kzg_params + restart: "no" # Prevent restart after completion + environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 + healthcheck: + test: [ "CMD", "test", "-f", "/app/kzg_params/health_check_3_5_18" ] + interval: 1m + timeout: 10s + retries: 10 + start_period: 10m + admin: build: context: . dockerfile: ops/docker/Dockerfile.admin container_name: zkrand_admin_service volumes: - - admin_volume:/data + - admin_volume:/app/data environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - RAND_GEN_INTERVAL=3600 @@ -25,12 +46,20 @@ services: dockerfile: ops/docker/Dockerfile.node container_name: zkrand_node_1_service volumes: - - node_1_volume:/data + - kzg_params_volume:/app/kzg_params + - node_1_volume:/app/data + entrypoint: [ "" ] environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - ZK_RAND_ADDRESS=0x1C2FfFeEee7d396597D60adAdAC63c2c48B829AF - NODE_PRIVATE_KEY=0x2e978a5709ac0dc3cbc2260519f8fcf5542af54dfaff489bcb4a69182be49429 + depends_on: + init: + condition: service_healthy node-two: @@ -39,12 +68,20 @@ services: dockerfile: ops/docker/Dockerfile.node container_name: zkrand_node_2_service volumes: - - node_2_volume:/data + - kzg_params_volume:/app/kzg_params + - node_2_volume:/app/data + entrypoint: [ "" ] environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - ZK_RAND_ADDRESS=0x1C2FfFeEee7d396597D60adAdAC63c2c48B829AF - NODE_PRIVATE_KEY=0xa0a98d2341d78ed222b7a6314c026d8e85185203fd295f67b7146be956a05c58 + depends_on: + init: + condition: service_healthy node-three: build: @@ -52,12 +89,20 @@ services: dockerfile: ops/docker/Dockerfile.node container_name: zkrand_node_3_service volumes: - - node_3_volume:/data + - kzg_params_volume:/app/kzg_params + - node_3_volume:/app/data + entrypoint: [ "" ] environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - ZK_RAND_ADDRESS=0x1C2FfFeEee7d396597D60adAdAC63c2c48B829AF - NODE_PRIVATE_KEY=0x742e271d909d026b2b4dcc0384ec0b8df8f674f0773c354b57c24858419e89d3 + depends_on: + init: + condition: service_healthy node-four: @@ -66,12 +111,20 @@ services: dockerfile: ops/docker/Dockerfile.node container_name: zkrand_node_4_service volumes: - - node_4_volume:/data + - kzg_params_volume:/app/kzg_params + - node_4_volume:/app/data + entrypoint: [ "" ] environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - ZK_RAND_ADDRESS=0x1C2FfFeEee7d396597D60adAdAC63c2c48B829AF - NODE_PRIVATE_KEY=0xeeb82181766c7d0fe45d2cb5b3399b1da17a1a432938ec8c4d73daca85eedaea + depends_on: + init: + condition: service_healthy node-five: @@ -80,15 +133,24 @@ services: dockerfile: ops/docker/Dockerfile.node container_name: zkrand_node_5_service volumes: - - node_5_volume:/data + - kzg_params_volume:/app/kzg_params + - node_5_volume:/app/data + entrypoint: [ "" ] environment: + - THRESHOLD=3 + - NUMBER_OF_MEMBERS=5 + - DEGREE=18 - L2_NODE_WEB3_URL=https://sepolia.boba.network - POLLING_INTERVAL=12000 - ZK_RAND_ADDRESS=0x1C2FfFeEee7d396597D60adAdAC63c2c48B829AF - NODE_PRIVATE_KEY=0x88b68d7e8d96d8465cfe3dc4abf707e21aa49139189a784e2d50cc9ada9076c3 + depends_on: + init: + condition: service_healthy volumes: + kzg_params_volume: admin_volume: node_1_volume: node_2_volume: diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..9f53ec6 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -uex + +echo "THRESHOLD: ${THRESHOLD}" +echo "NUMBER_OF_MEMBERS: ${NUMBER_OF_MEMBERS}" +echo "DEGREE: ${DEGREE}" + +params_dir="kzg_params" +degree_output_file="$params_dir/params${DEGREE}" + +# Check if the file already exists +if [ -f "$degree_output_file" ]; then + echo "File $degree_output_file already exists. Skipping download." +else + # If the file does not exist, proceed with the download + echo "File $degree_output_file does not exist. Downloading..." + axel -ac https://axiom-crypto.s3.amazonaws.com/challenge_0085/kzg_bn254_"${DEGREE}".srs -o "$degree_output_file" + + # Check if the download was successful + if [ $? -eq 0 ]; then + echo "Download completed." + else + echo "Download failed." >&2 + exit 1 + fi +fi + +RUST_LOG=info ./target/release/client config $THRESHOLD $NUMBER_OF_MEMBERS $DEGREE +RUST_LOG=info ./target/release/client setup --skip + +# Touch a health check file to indicate readiness +touch "$params_dir/health_check_${THRESHOLD}_${NUMBER_OF_MEMBERS}_${DEGREE}" + +# Execute the main command or default to shell +exec "$@" \ No newline at end of file diff --git a/ops/docker/Dockerfile.admin b/ops/docker/Dockerfile.admin index ce74e87..c7dea50 100644 --- a/ops/docker/Dockerfile.admin +++ b/ops/docker/Dockerfile.admin @@ -12,6 +12,9 @@ RUN apt-get install -y \ ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib +# Create a working directory +WORKDIR /app + COPY ./package.json . RUN yarn install @@ -27,12 +30,9 @@ COPY ./src ./src ENV PATH="/root/.cargo/bin:${PATH}" RUN cargo build --release -COPY download_params.sh . -RUN chmod +x download_params.sh -RUN ./download_params.sh - COPY ./data ./data -RUN RUST_LOG=info ./target/release/client setup -s +# Declare the directory as a volume +VOLUME /app/data COPY ./tsconfig.json . COPY ./services ./services diff --git a/ops/docker/Dockerfile.init b/ops/docker/Dockerfile.init new file mode 100644 index 0000000..d5f59f6 --- /dev/null +++ b/ops/docker/Dockerfile.init @@ -0,0 +1,34 @@ +FROM node:20 + +RUN apt-get update && apt-get install -y curl \ + && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> $HOME/.bashrc + +RUN apt-get install -y \ + llvm \ + clang \ + libclang-dev \ + axel + +ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib + +# Create a working directory +WORKDIR /app + +COPY ./Cargo.toml . +COPY ./Cargo.lock . +COPY ./bin ./bin +COPY ./benches ./benches +COPY ./src ./src +ENV PATH="/root/.cargo/bin:${PATH}" +RUN cargo build --release + +COPY ./data ./data + +# Declare the directory as a volume +VOLUME /app/kzg_params + +COPY entrypoint.sh ./entrypoint.sh +RUN chmod +x ./entrypoint.sh + +ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/ops/docker/Dockerfile.node b/ops/docker/Dockerfile.node index da76b9b..e06c4e5 100644 --- a/ops/docker/Dockerfile.node +++ b/ops/docker/Dockerfile.node @@ -12,6 +12,9 @@ RUN apt-get install -y \ ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib +# Create a working directory +WORKDIR /app + COPY ./package.json . RUN yarn install @@ -27,12 +30,16 @@ COPY ./src ./src ENV PATH="/root/.cargo/bin:${PATH}" RUN cargo build --release -COPY download_params.sh . -RUN chmod +x download_params.sh -RUN ./download_params.sh +# Declare the directory as a volume +VOLUME /app/kzg_params +# Declare the directory as a volume COPY ./data ./data -RUN RUST_LOG=info ./target/release/client setup -s +VOLUME /app/data + +COPY entrypoint.sh ./entrypoint.sh +RUN chmod +x ./entrypoint.sh +ENTRYPOINT ["./entrypoint.sh"] COPY ./tsconfig.json . COPY ./services ./services diff --git a/services/admin.ts b/services/admin.ts index 361f7e9..dcc22f5 100644 --- a/services/admin.ts +++ b/services/admin.ts @@ -33,6 +33,9 @@ export interface GasPriceOverride { } interface AdminZkRandOptions { + threshold: number + numberMembers: number + degree: number l2RpcProvider: providers.StaticJsonRpcProvider l2Wallet: Wallet // chain ID of the L2 network @@ -93,10 +96,12 @@ export class AdminZkRandService extends BaseService { this.state.timeOfLastRound = 0 // 0 indicates no round has been initiated this.state.startDate = 0 - let startDate = new Date(this.options.randGenStartDate); + let startDate = new Date(this.options.randGenStartDate) if (!isNaN(startDate.getTime())) { this.state.startDate = startDate.getTime() } + + await this.config() } async _start(): Promise { @@ -110,13 +115,11 @@ export class AdminZkRandService extends BaseService { ) } - let threshold = await this.state.zkRandContract.threshold() - let memberCountFromContract = await this.state.zkRandContract.memberCount() - console.log("memberCountFromContract", memberCountFromContract) + let currentIndexFromContract = await this.state.zkRandContract.currentIndex() console.log("currentIndexFromContract", currentIndexFromContract) - if (currentIndexFromContract != memberCountFromContract) { + if (currentIndexFromContract != this.options.numberMembers) { // check if nidkg is already completed, or if this step is already done console.log("adding permissioned nodes") const nodeOne = await this.state.zkRandContract.addrToNode(this.options.nodeOneAddress) @@ -180,7 +183,7 @@ export class AdminZkRandService extends BaseService { let submissionCount = await this.state.zkRandContract.roundSubmissionCount(currentRoundNum) let roundToRandom = await this.state.zkRandContract.roundToRandom(currentRoundNum) - if (roundToRandom.value === bytes32Zero && submissionCount >= threshold) { + if (roundToRandom.value === bytes32Zero && submissionCount >= this.options.threshold) { await this.createRandom(currentRoundNum) } @@ -265,6 +268,27 @@ export class AdminZkRandService extends BaseService { }); } + async config() { + let threshold = await this.state.zkRandContract.threshold() + if (threshold != this.options.threshold) { + throw new Error( + `threshold=${this.options.threshold} does not match threshold=${threshold} from contract` + ) + } + let memberCountFromContract = await this.state.zkRandContract.memberCount() + if (memberCountFromContract != this.options.numberMembers) { + throw new Error( + `number_of_members=${this.options.numberMembers} does not match number_of_members=${memberCountFromContract} from contract` + ) + } + console.log("memberCountFromContract", memberCountFromContract) + + const cmd = `RUST_LOG=info ./target/release/client config ${this.options.threshold} ${this.options.numberMembers} ${this.options.degree}` + console.log("running command <", cmd, ">...") + let result = await execPromise(cmd) + console.log(result[`stderr`]) + } + async createGpp() { // read all instances from contract diff --git a/services/exec/run.ts b/services/exec/run.ts index e57640d..7fccb8e 100644 --- a/services/exec/run.ts +++ b/services/exec/run.ts @@ -16,6 +16,11 @@ const main = async () => { }) const env = process.env + + const THRESHOLD = config.uint("threshold", parseInt(env.THRESHOLD, 10)) + const NUMBER_OF_MEMBERS = config.uint("number_of_members", parseInt(env.NUMBER_OF_MEMBERS, 10)) + const DEGREE = config.uint("threshold", parseInt(env.DEGREE, 10)) + const L2_NODE_WEB3_URL = config.str('l2-node-web3-url', env.L2_NODE_WEB3_URL) const ADMIN_PRIVATE_KEY = config.str('admin-private-key', env.ADMIN_PRIVATE_KEY) @@ -52,6 +57,9 @@ const main = async () => { const chainId = (await l2Provider.getNetwork()).chainId const service = new AdminZkRandService({ + threshold: THRESHOLD, + numberMembers: NUMBER_OF_MEMBERS, + degree: DEGREE, l2RpcProvider: l2Provider, l2Wallet: wallet, chainId, diff --git a/services/exec/runNode.ts b/services/exec/runNode.ts index 20423cc..3179546 100644 --- a/services/exec/runNode.ts +++ b/services/exec/runNode.ts @@ -16,6 +16,11 @@ const main = async () => { }) const env = process.env + + const THRESHOLD = config.uint("threshold", parseInt(env.THRESHOLD, 10)) + const NUMBER_OF_MEMBERS = config.uint("number_of_members", parseInt(env.NUMBER_OF_MEMBERS, 10)) + const DEGREE = config.uint("threshold", parseInt(env.DEGREE, 10)) + const L2_NODE_WEB3_URL = config.str('l2-node-web3-url', env.L2_NODE_WEB3_URL) const NODE_PRIVATE_KEY = config.str('node-private-key', env.NODE_PRIVATE_KEY) @@ -39,6 +44,9 @@ const main = async () => { const chainId = (await l2Provider.getNetwork()).chainId const service = new NodeZkRandService({ + threshold: THRESHOLD, + numberMembers: NUMBER_OF_MEMBERS, + degree: DEGREE, l2RpcProvider: l2Provider, l2Wallet: wallet, chainId, diff --git a/services/node.ts b/services/node.ts index 2641418..79f5c77 100644 --- a/services/node.ts +++ b/services/node.ts @@ -29,6 +29,9 @@ export interface GasPriceOverride { } interface NodeZkRandOptions { + threshold: number + numberMembers: number + degree: number l2RpcProvider: providers.StaticJsonRpcProvider l2Wallet: Wallet // chain ID of the L2 network @@ -74,6 +77,7 @@ export class NodeZkRandService extends BaseService { this.state.gasOverride = {gasLimit: 10000000} + await this.config() } async _start(): Promise { @@ -120,6 +124,27 @@ export class NodeZkRandService extends BaseService { } } + async config() { + let threshold = await this.state.zkRandContract.threshold() + if (threshold != this.options.threshold) { + throw new Error( + `threshold=${this.options.threshold} does not match threshold=${threshold} from contract` + ) + } + let memberCountFromContract = await this.state.zkRandContract.memberCount() + if (memberCountFromContract != this.options.numberMembers) { + throw new Error( + `number_of_members=${this.options.numberMembers} does not match number_of_members=${memberCountFromContract} from contract` + ) + } + console.log("memberCountFromContract", memberCountFromContract) + + const cmd = `RUST_LOG=info ./target/release/client config ${this.options.threshold} ${this.options.numberMembers} ${this.options.degree}` + console.log("running command <", cmd, ">...") + let result = await execPromise(cmd) + console.log(result[`stderr`]) + } + async registerNode() { // generate member secret key and member public key on grumpkin curve const index = this.options.l2Wallet.address From d7657ee734e3843e0e9b75296a423c2eaecff7ca Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Fri, 26 Jul 2024 15:43:09 +0100 Subject: [PATCH 2/8] use axiom crypto link for trusted setup --- download_params.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/download_params.sh b/download_params.sh index bd48eca..1b6c7cc 100644 --- a/download_params.sh +++ b/download_params.sh @@ -9,5 +9,5 @@ mkdir -p "$params_dir" degree_output_file="$params_dir"/params"${degree}" rm -f "$degree_output_file" -axel -ac https://trusted-setup-halo2kzg.s3.eu-central-1.amazonaws.com/perpetual-powers-of-tau-raw-"$degree" -o "$degree_output_file" - +# https://docs.axiom.xyz/docs/transparency-and-security/kzg-trusted-setup +axel -ac https://axiom-crypto.s3.amazonaws.com/challenge_0085/kzg_bn254_"${degree}".srs -o "$degree_output_file" \ No newline at end of file From 04c5d531b14b2ea523ebf878cf186d3ff6e9367f Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Mon, 29 Jul 2024 10:39:32 +0100 Subject: [PATCH 3/8] use env variables for rust client --- Cargo.lock | 167 ++-------------------------------------------- Cargo.toml | 13 ++-- README.md | 71 ++++++++++---------- bin/client.rs | 101 +++++++++++++--------------- entrypoint.sh | 15 ++--- services/admin.ts | 26 ++++---- services/node.ts | 28 ++++---- 7 files changed, 124 insertions(+), 297 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9daae57..62754b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.7" @@ -317,17 +306,6 @@ dependencies = [ "nom", ] -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "atty" version = "0.2.14" @@ -363,12 +341,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64ct" version = "1.6.0" @@ -663,25 +635,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "config" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" -dependencies = [ - "async-trait", - "json5", - "lazy_static", - "nom", - "pathdiff", - "ron", - "rust-ini", - "serde", - "serde_json", - "toml", - "yaml-rust", -] - [[package]] name = "const-hex" version = "1.10.0" @@ -887,10 +840,10 @@ dependencies = [ ] [[package]] -name = "dlv-list" -version = "0.3.0" +name = "dotenv" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "ecc" @@ -1164,9 +1117,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] [[package]] name = "hashbrown" @@ -1174,7 +1124,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash 0.8.7", + "ahash", "allocator-api2", ] @@ -1332,17 +1282,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - [[package]] name = "k256" version = "0.13.3" @@ -1402,12 +1341,6 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.4.12" @@ -1577,16 +1510,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "ordered-multimap" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" -dependencies = [ - "dlv-list", - "hashbrown 0.12.3", -] - [[package]] name = "os_str_bytes" version = "6.6.1" @@ -1640,12 +1563,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - [[package]] name = "peeking_take_while" version = "0.1.2" @@ -1663,40 +1580,6 @@ dependencies = [ "ucd-trie", ] -[[package]] -name = "pest_derive" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "pest_meta" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2024,17 +1907,6 @@ dependencies = [ "rustc-hex", ] -[[package]] -name = "ron" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" -dependencies = [ - "base64", - "bitflags 1.3.2", - "serde", -] - [[package]] name = "ruint" version = "1.11.1" @@ -2065,16 +1937,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" -[[package]] -name = "rust-ini" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - [[package]] name = "rustc-hash" version = "1.1.0" @@ -2407,15 +2269,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.6.3" @@ -2806,15 +2659,6 @@ dependencies = [ "tap", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zerocopy" version = "0.7.32" @@ -2863,9 +2707,9 @@ dependencies = [ "ark-std 0.3.0", "blake2b_simd", "clap 4.4.18", - "config", "const_format", "criterion", + "dotenv", "ecc", "env_logger 0.9.3", "halo2_gadgets", @@ -2886,5 +2730,4 @@ dependencies = [ "static_assertions", "subtle", "thiserror", - "toml", ] diff --git a/Cargo.toml b/Cargo.toml index f33633b..750c66a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,11 @@ edition = "2021" [dependencies] lazy_static = "1.4.0" -halo2_gadgets = { git = "https://github.com/kitounliu/halo2.git", branch = "grumpkin"} -halo2wrong = { git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin"} -halo2_ecc ={ package = "ecc", git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin"} -halo2_maingate = { package = "maingate", git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin"} -halo2_proofs = { git = "https://github.com/kitounliu/halo2.git", branch = "grumpkin"} +halo2_gadgets = { git = "https://github.com/kitounliu/halo2.git", branch = "grumpkin" } +halo2wrong = { git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin" } +halo2_ecc = { package = "ecc", git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin" } +halo2_maingate = { package = "maingate", git = "https://github.com/kitounliu/halo2wrong.git", branch = "grumpkin" } +halo2_proofs = { git = "https://github.com/kitounliu/halo2.git", branch = "grumpkin" } sha3 = "0.10" rand_core = { version = "0.6", default-features = false } @@ -26,8 +26,6 @@ serde = { version = "1.0.193", features = ["derive"] } # for client clap = { version = "4.4.18", features = ["derive"] } -config = "0.13.4" -toml = "0.5.11" serde_json = "1.0.108" rand_chacha = "0.3.1" ark-std = { version = "0.3", features = ["print-trace"] } @@ -36,6 +34,7 @@ const_format = "0.2.32" pretty_env_logger = "0.5.0" thiserror = "1.0" hex = "0.4.3" +dotenv = "0.15" [dev-dependencies] rand_chacha = "0.3.1" diff --git a/README.md b/README.md index 7773351..90b02c5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ zkRand is a t-out-of-n threshold scheme that runs among a group of n distributed members. The protocol consists of two components: -a snark-based non-interactive distributed key generation (NI-DKG) and randomness generation based on threshold +a snark-based non-interactive distributed key generation (NIDKG) and randomness generation based on threshold bls-signatures. ### To build: @@ -26,28 +26,25 @@ $ ./target/release/client -h This downloads KZG parameters with degree = 22 from Ethereum Powers of Tau. The parameters are saved in "./kzg_params/params22". This is the KZG ceremony. -2. Config. This step initialises the protocol configuration. - The default config is set to be (threshold, number_of_memnbers, degree) = (3, 5, 18). - This can be changed by: - ``` - $ RUST_LOG=info ./target/release/client config - ``` - The configuration is saved at "data/config.toml". The degree determines maximum number of gates allowed in a DNI-KG +2. Config. The default config is set to be (THRESHOLD, NUMBER_OF_MEMBERS, DEGREE=18) = (3, 5, 18). + These are environment variables that need to be used consistently throughout the protocol. + You can set their values in the .env file. + The degree determines maximum number of gates allowed in a NIDKG circuit. - Higher degree is required for supporting more members in the NI-DKG protocol. + Higher degree is required for supporting more members in the NIDKG protocol. The maximun (threshold, number_of_members) that can be supported for a given degree is: | degree | 18 | 19 | 20 | 21 | 22 | - |:------:|:------:| :----: | :----: | :----: | :----: | + |:------:|:------:| :----: | :----: | :----: | :----: | | (t, n) | (3, 5) | (9, 16) | (20, 38) | (42, 83) | (86, 171) The threshold is set as the majority of number_of_members. -3. Setup. This generates SNARK proving key and verifying key for NI-DKG circuits, +3. Setup. This generates SNARK proving key and verifying key for NIDKG circuits, and the verification contracts for checking SNARK proofs onchain. The SNARK parameters are generated using: ``` - $ RUST_LOG=info ./target/release/client setup --split + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client setup --split ``` The parameters are computed using Ethereum power-of-tau, therefore, the proving/verifying keys are deterministic given a configuration. @@ -56,10 +53,10 @@ $ ./target/release/client -h stays the same for different (t,n) values. The verifying key contract needs to be changed when (t,n) changes. The current implementation of contracts set (t,n) to be (3, 5). -4. KeyGen. Before the NI-DKG protocol starts, each member $i$ pre-generates its member public key $mpk_i$ and - secret key $msk_i$ for encryption and decryption in NI-DKG protocol: +4. KeyGen. Before the NIDKG protocol starts, each member $i$ pre-generates its member public key $mpk_i$ and + secret key $msk_i$ for encryption and decryption in NIDKG protocol: ``` - $ RUST_LOG=info ./target/release/client keygen + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client keygen ``` The secret key is saved at "./data/members/member.json". The public key is printed in the format: ``` @@ -73,7 +70,7 @@ $ ./target/release/client -h Each member submits its member public key to contract "zkdvrf.sol" through function `registerNode`. The hex string may need to be converted to big integers before submitting to the contract. In the contract, all the submitted public keys are stored in `pubKeys` and their order is stored in `ppListOrder`. - To use these public keys in the following NI-DKG steps, `pubKeys` should be converted to a list that is compatible + To use these public keys in the following NIDKG steps, `pubKeys` should be converted to a list that is compatible with the Rust backend: ``` @@ -90,11 +87,11 @@ $ ./target/release/client -h for the next steps. -5. NI-DKG. +5. NIDKG. 1. Create public parameters. Each member $i$ selects a random polynomial to create its public parameters $pp_i$ and a SNARK proof $zkp_i$ to ensure the parameters are generated correctly. ``` - $ RUST_LOG=info ./target/release/client dkg prove + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client dkg prove ``` Index is the member's position in the list of member public keys. The index ranges 1, 2, ..., number_of_members. This command reads "./data/mpks.json" to obtain all members public keys. @@ -110,15 +107,15 @@ $ ./target/release/client -h $(pp_i, zpk_i)$ can also be verified locally using ``` - $ RUST_LOG=info ./target/release/client dkg verify + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client dkg verify ``` This command reads $pp_i$ from "./data/dkg/proofs/instance_{INDEX}.json" and $zkp_i$ from "./data/dkg/proofs/proof_{INDEX}.dat". The current implementation of contracts expect submission from each member. However, it is in fact not necessary to require each member to generate and submit $pp_i$. - Instead, a lower bound $m$ with threshold < m <= number_of_members can be set to accept the NI-DKG process. - For example, m = (2/3) * number_of_members. If at least m members submit valid $(pp_i, zkp_i)$, then the NI-DKG + Instead, a lower bound $m$ with threshold < m <= number_of_members can be set to accept the NIDKG process. + For example, m = (2/3) * number_of_members. If at least m members submit valid $(pp_i, zkp_i)$, then the NIDKG can be considered successfully. The members that do not submit will still be able to obtain a secret/verification key pair (in the following steps) as long as their member public keys are included. @@ -129,7 +126,7 @@ $ ./target/release/client -h Member $i$ can derive its secret share $sk_i$ and the global public parameters using: ``` - $ RUST_LOG=info ./target/release/client dkg derive -f + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client dkg derive -f ``` This command requires member $i$'s secret key $msk_i$ in "./data/members/FILE.json" and all the public parameters in "./data/all_instances.json". The default value of FILE is "member". `ppList` in the contract @@ -140,7 +137,7 @@ $ ./target/release/client -h ./data/gpk.json" and all the verification keys saved at "./data/vks.json". Every member can obtain a verification key regardless of whether the - member participates in the NI-DKG or not. The verification keys are listed in the same order as the member public + member participates in the NIDKG or not. The verification keys are listed in the same order as the member public keys. The verification key $vk_i$ will be used to verify the partial evaluation generation by member $i$ using its secret share $sk_i$. @@ -150,7 +147,7 @@ $ ./target/release/client -h `verifyPseudoRand` given $gpk$ and $x$. 1. Each member $i$ computes a partial evaluation $eval_i$ using: ``` - $ RUST_LOG=info ./target/release/client rand eval + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client rand eval ``` This command reads member $i$'s secret share $sk_i$ from "./data/dkg/shares/share_{INDEX}.json". The output of $eval_i$ is saved at "./data/random/eval_{INDEX}.json". @@ -167,7 +164,7 @@ $ ./target/release/client -h All the hex string may need to be converted to big integers before submitting to the contract. $eval_i$ can also be verified locally using ``` - $ RUST_LOG=info ./target/release/client rand verify + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client rand verify ``` This command reads $eval_i$ from "./data/random/eval_{INDEX}.json" and verification keys from "./data/vks.json". @@ -177,7 +174,7 @@ $ ./target/release/client -h onchain verification cost, the combination can be done offchain and only the final pseudorandom value and its proof needs to be verified onchain. ``` - $ RUST_LOG=info ./target/release/client rand combine + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client rand combine ``` This command reads all partial evaluations from "./data/evals.json" and outputs a pseudorandom value saved at "./data/random/pseudo.json". @@ -208,7 +205,7 @@ $ ./target/release/client -h The pseudorandom value can also be verified locally: ``` - $ RUST_LOG=info ./target/release/client rand verify-final + $ RUST_LOG=info THRESHOLD= NUMBER_OF_MEMBERS= DEGREE= ./target/release/client rand verify-final ``` This command reads pseudorandom from "./data/random/pseudo.json". @@ -216,16 +213,20 @@ $ ./target/release/client -h To deploy the zkRand contracts on-chain- -1. Set up your .env (use .env.example for reference) +1. Set up your .env (use .env.example.deploy for reference) ``` -RPC_URL = -PRIVATE_KEY = -DEPLOY_NO_HELPERS = # optional -HALO2V = # optional -HALO2VK = # optional -GPP = # optional -PSRAND = # optional +L2_NODE_WEB3_URL= +DEPLOYER_PRIVATE_KEY= +ADMIN_ADDRESS= +THRESHOLD=3 +NUMBER_OF_MEMBERS=5 +DEGREE=18 +DEPLOY_NO_HELPERS=false # optional +HALO2VK=0x63311f167b6B07fd0D3d83310c16512701B4Cb2d # optional +HALO2V=0x26Aa5a7c4CA7D0F81943ea9CbDf97D80c560D6Fa # optional +GPP=0xbB9a8f4c3662b6EF4b512E5f358289d1Db63fc81 # optional +PSRAND=0xAecFC1cc68dD9664F2fCF5f2958d5277c5385123 # optional ``` deploying the helpers are optional, and to proceed with using prior-deployed helpers, set `DEPLOY_NO_HELPERS` to true diff --git a/bin/client.rs b/bin/client.rs index 524c5bc..c0a43fe 100644 --- a/bin/client.rs +++ b/bin/client.rs @@ -1,8 +1,16 @@ +use crate::mock::{mock_dkg, mock_members, mock_random}; +use crate::proof::{create_proof_checked, verify_single}; +use crate::serialise::{ + hex_to_le_bytes, le_bytes_to_hex, DkgGlobalPubParams as DkgGlobalPubParamsSerde, + DkgMemberParams as DkgMemberParamsSerde, DkgShareKey as DkgShareKeySerde, + MemberKey as MemberKeySerde, PartialEval as PartialEvalSerde, Point, Point2, + PseudoRandom as PseudoRandomSerde, +}; use anyhow::{anyhow, Result}; use ark_std::{end_timer, start_timer}; use clap::{Args, Parser, Subcommand}; -use config::Config; use const_format::formatcp; +use dotenv::dotenv; use halo2_ecc::halo2::halo2curves::bn256::{Fr as BnScalar, G1Affine as BnG1, G2Affine as BnG2}; use halo2_solidity_verifier::BatchOpenScheme::Bdfg21; use halo2_solidity_verifier::SolidityGenerator; @@ -14,17 +22,8 @@ use pretty_env_logger; use rand_chacha::ChaCha20Rng; use rand_core::{OsRng, RngCore, SeedableRng}; use serde::{Deserialize, Serialize}; +use std::env; use std::fs::{create_dir_all, read, read_to_string, write}; -use toml::to_string_pretty; - -use crate::mock::{mock_dkg, mock_members, mock_random}; -use crate::proof::{create_proof_checked, verify_single}; -use crate::serialise::{ - hex_to_le_bytes, le_bytes_to_hex, DkgGlobalPubParams as DkgGlobalPubParamsSerde, - DkgMemberParams as DkgMemberParamsSerde, DkgShareKey as DkgShareKeySerde, - MemberKey as MemberKeySerde, PartialEval as PartialEvalSerde, Point, Point2, - PseudoRandom as PseudoRandomSerde, -}; #[cfg(not(feature = "g2chip"))] use serialise::DkgMemberPublicParams as DkgMemberPublicParamsSerde; @@ -43,7 +42,6 @@ mod serialise; const KZG_PARAMS_DIR: &str = "./kzg_params"; const CONTRACT_DIR: &str = "./contracts"; const DATA_DIR: &str = "./data"; -const CONFIG_PATH: &str = formatcp!("{}/config.toml", DATA_DIR); const MEM_PUBLIC_KEYS_PATH: &str = formatcp!("{}/mpks.json", DATA_DIR); const MEMBERS_DIR: &str = formatcp!("{}/members", DATA_DIR); const DKG_DIR: &str = formatcp!("{}/dkg", DATA_DIR); @@ -62,12 +60,6 @@ struct Cli { #[derive(Subcommand)] enum Commands { - /// Set (threshold, number of members, degree) in config - Config { - threshold: u32, - number_of_members: u32, - degree: u32, - }, /// Mock n members and dkg parameters Mock(MockArgs), /// Generate kzg parameters, proving key and verifying key for SNARKs and verifier contract @@ -174,26 +166,6 @@ impl ParamsConfig { } } -fn update_config(threshold: u32, number_of_members: u32, degree: u32) -> Result<()> { - let min_threshold = (number_of_members + 2) / 2; - if threshold < min_threshold || threshold > number_of_members { - return Err(anyhow!("Invalid threshold")); - } - - let params = ParamsConfig { - threshold, - number_of_members, - degree, - }; - let toml_str = to_string_pretty(¶ms)?; - - // Write the TOML string to a file - write(CONFIG_PATH, toml_str)?; - info!("config saved in {CONFIG_PATH}"); - - Ok(()) -} - fn save_share(share: &DkgShareKey) -> Result<()> { let index = share.index(); let path = &format!("{DKG_SHARES_DIR}/share_{index}.json"); @@ -336,17 +308,9 @@ fn setup(params: &ParamsConfig, skip: bool, split: bool) -> Result<()> { Ok(()) } -fn load_config() -> Result { - let settings = Config::builder() - .add_source(config::File::with_name(CONFIG_PATH)) - .build()?; - let params: ParamsConfig = settings.try_deserialize()?; - // todo: automatically generate or check degree - Ok(params) -} - fn main() -> Result<()> { pretty_env_logger::init(); + // let mut rng = ChaCha20Rng::seed_from_u64(42); let mut rng = OsRng; @@ -357,18 +321,45 @@ fn main() -> Result<()> { create_dir_all(CONTRACT_DIR)?; create_dir_all(RANDOM_DIR)?; - let params = load_config()?; + // Load environment variables from .env file if it exists + dotenv().ok(); + + let is_any_var_missing_or_invalid = |keys: &[&str]| { + keys.iter().any(|&key| { + env::var(key) + .ok() + .and_then(|val| val.parse::().ok()) + .is_none() + }) + }; + + let config_keys = ["THRESHOLD", "NUMBER_OF_MEMBERS", "DEGREE"]; + let default_values: (u32, u32, u32) = (3, 5, 18); + let (threshold, number_of_members, degree) = if is_any_var_missing_or_invalid(&config_keys) { + info!("One or more env variables are missing or invalid. Using default config"); + default_values + } else { + ( + env::var(config_keys[0]).unwrap().parse::().unwrap(), + env::var(config_keys[1]).unwrap().parse::().unwrap(), + env::var(config_keys[2]).unwrap().parse::().unwrap(), + ) + }; + + info!( + "(threshold, number_of_members, degree) = ({}, {}, {})", + threshold, number_of_members, degree + ); + + let params = ParamsConfig { + threshold, + number_of_members, + degree, + }; let dkg_config = params.dkg_config()?; let cli = Cli::parse(); match cli.command { - Commands::Config { - threshold, - number_of_members, - degree, - } => { - update_config(threshold, number_of_members, degree)?; - } Commands::Mock(mock) => { if mock.members { mock_members(&dkg_config, &mut rng)?; diff --git a/entrypoint.sh b/entrypoint.sh index 9f53ec6..08f6268 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -14,19 +14,16 @@ if [ -f "$degree_output_file" ]; then else # If the file does not exist, proceed with the download echo "File $degree_output_file does not exist. Downloading..." - axel -ac https://axiom-crypto.s3.amazonaws.com/challenge_0085/kzg_bn254_"${DEGREE}".srs -o "$degree_output_file" - - # Check if the download was successful - if [ $? -eq 0 ]; then - echo "Download completed." + # Use curl with error handling + if curl -f -o "$degree_output_file" "https://axiom-crypto.s3.amazonaws.com/challenge_0085/kzg_bn254_${DEGREE}.srs"; then + echo "Download completed." else - echo "Download failed." >&2 - exit 1 + echo "Download failed." >&2 + exit 1 fi fi -RUST_LOG=info ./target/release/client config $THRESHOLD $NUMBER_OF_MEMBERS $DEGREE -RUST_LOG=info ./target/release/client setup --skip +RUST_LOG=info THRESHOLD=$THRESHOLD NUMBER_OF_MEMBERS=$NUMBER_OF_MEMBERS DEGREE=$DEGREE ./target/release/client setup --skip # Touch a health check file to indicate readiness touch "$params_dir/health_check_${THRESHOLD}_${NUMBER_OF_MEMBERS}_${DEGREE}" diff --git a/services/admin.ts b/services/admin.ts index dcc22f5..b79b14d 100644 --- a/services/admin.ts +++ b/services/admin.ts @@ -3,7 +3,6 @@ import {Contract, Wallet, BigNumber, providers} from 'ethers' import fs from "fs"; import {promisify} from "util"; import {exec} from "child_process"; - import {sleep} from '@eth-optimism/core-utils' import {BaseService} from '@eth-optimism/common-ts' @@ -71,6 +70,8 @@ export class AdminZkRandService extends BaseService { startDate: number } = {} as any + private cmdPrefix: string; + async _init(): Promise { this.logger.info('Initializing AdminZkRand service...', { options: this.options, @@ -101,7 +102,9 @@ export class AdminZkRandService extends BaseService { this.state.startDate = startDate.getTime() } - await this.config() + this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} ./target/release/client` + + await this.check_config() } async _start(): Promise { @@ -233,7 +236,7 @@ export class AdminZkRandService extends BaseService { await sleep(2000) // derive global public parameters - const cmd = `RUST_LOG=info ./target/release/client dkg derive` + const cmd = `${this.cmdPrefix} dkg derive` console.log("running command <", cmd, ">...") let result = await execPromise(cmd) console.log(result[`stderr`]) @@ -268,7 +271,7 @@ export class AdminZkRandService extends BaseService { }); } - async config() { + async check_config() { let threshold = await this.state.zkRandContract.threshold() if (threshold != this.options.threshold) { throw new Error( @@ -282,11 +285,6 @@ export class AdminZkRandService extends BaseService { ) } console.log("memberCountFromContract", memberCountFromContract) - - const cmd = `RUST_LOG=info ./target/release/client config ${this.options.threshold} ${this.options.numberMembers} ${this.options.degree}` - console.log("running command <", cmd, ">...") - let result = await execPromise(cmd) - console.log(result[`stderr`]) } @@ -304,7 +302,7 @@ export class AdminZkRandService extends BaseService { await sleep(2000) // derive global public parameters - const cmd = `RUST_LOG=info ./target/release/client dkg derive` + const cmd = `${this.cmdPrefix} dkg derive` console.log("running command <", cmd, ">...") let result = await execPromise(cmd) console.log(result[`stderr`]) @@ -383,12 +381,12 @@ export class AdminZkRandService extends BaseService { console.log("sleeping..") await sleep(2000) - const cmdCombine = `RUST_LOG=info ./target/release/client rand combine "${input}"` + const cmdCombine = `${this.cmdPrefix} rand combine "${input}"` console.log("running command <", cmdCombine, ">...") let result = await execPromise(cmdCombine) console.log(result[`stderr`]) - const cmdVerify = `RUST_LOG=info ./target/release/client rand verify-final "${input}"` + const cmdVerify = `${this.cmdPrefix} rand verify-final "${input}"` console.log("running command <", cmdVerify, ">...") result = await execPromise(cmdVerify) console.log(result[`stderr`]) @@ -439,12 +437,12 @@ export class AdminZkRandService extends BaseService { console.log("sleep..") await sleep(2000) - const cmdCombine = `RUST_LOG=info ./target/release/client rand combine "${input}"` + const cmdCombine = `${this.cmdPrefix} rand combine "${input}"` console.log("running command <", cmdCombine, ">...") let result = await execPromise(cmdCombine) console.log(result[`stderr`]) - const cmdVerify = `RUST_LOG=info ./target/release/client rand verify-final "${input}"` + const cmdVerify = `${this.cmdPrefix} rand verify-final "${input}"` console.log("running command <", cmdVerify, ">...") result = await execPromise(cmdVerify) console.log(result[`stderr`]) diff --git a/services/node.ts b/services/node.ts index 79f5c77..8c0fe0f 100644 --- a/services/node.ts +++ b/services/node.ts @@ -3,7 +3,6 @@ import {Contract, Wallet, providers} from 'ethers' import fs from "fs"; import {promisify} from "util"; import {exec} from "child_process"; - import {sleep} from '@eth-optimism/core-utils' import {BaseService} from '@eth-optimism/common-ts' @@ -54,6 +53,8 @@ export class NodeZkRandService extends BaseService { gasOverride: GasPriceOverride } = {} as any + private cmdPrefix: string; + async _init(): Promise { this.logger.info('Initializing NodeZkRand service...', { options: this.options, @@ -77,7 +78,9 @@ export class NodeZkRandService extends BaseService { this.state.gasOverride = {gasLimit: 10000000} - await this.config() + this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} ./target/release/client` + + await this.check_config() } async _start(): Promise { @@ -124,7 +127,7 @@ export class NodeZkRandService extends BaseService { } } - async config() { + async check_config() { let threshold = await this.state.zkRandContract.threshold() if (threshold != this.options.threshold) { throw new Error( @@ -138,18 +141,13 @@ export class NodeZkRandService extends BaseService { ) } console.log("memberCountFromContract", memberCountFromContract) - - const cmd = `RUST_LOG=info ./target/release/client config ${this.options.threshold} ${this.options.numberMembers} ${this.options.degree}` - console.log("running command <", cmd, ">...") - let result = await execPromise(cmd) - console.log(result[`stderr`]) } async registerNode() { // generate member secret key and member public key on grumpkin curve const index = this.options.l2Wallet.address const file = `member_${index}` - const command = `RUST_LOG=info ./target/release/client keygen -f ${file}` + const command = `${this.cmdPrefix} keygen -f ${file}` console.log("running command <", command, ">...") const result = await execPromise(command); @@ -197,7 +195,7 @@ export class NodeZkRandService extends BaseService { await sleep(1000) // each member derives its own secret share and global public parameters - const cmd = `RUST_LOG=info ./target/release/client dkg derive` + const cmd = `${this.cmdPrefix} dkg derive` const index = await this.state.zkRandContract.getIndexPlus(this.options.l2Wallet.address) const cmdMember = cmd + ` ${index} -f member_${this.options.l2Wallet.address}` console.log("running command <", cmdMember, ">...") @@ -216,8 +214,8 @@ export class NodeZkRandService extends BaseService { await sleep(1000) const index = await this.state.zkRandContract.getIndexPlus(this.options.l2Wallet.address) - const cmdProve = `RUST_LOG=info ./target/release/client dkg prove ${index}` - const cmdVerify = `RUST_LOG=info ./target/release/client dkg verify ${index}` + const cmdProve = `${this.cmdPrefix} dkg prove ${index}` + const cmdVerify = `${this.cmdPrefix} dkg verify ${index}` // generate snark proof and instance console.log("running command <", cmdProve, ">...") @@ -255,7 +253,7 @@ export class NodeZkRandService extends BaseService { await sleep(2000) // each member derives its own secret share and global public parameters - const cmd = `RUST_LOG=info ./target/release/client dkg derive` + const cmd = `${this.cmdPrefix} dkg derive` const index = await this.state.zkRandContract.getIndexPlus(this.options.l2Wallet.address) const cmdMember = cmd + ` ${index} -f member_${this.options.l2Wallet.address}` console.log("running command <", cmdMember, ">...") @@ -268,8 +266,8 @@ export class NodeZkRandService extends BaseService { const input = await this.state.zkRandContract.roundInput(currentRound) const index = await this.state.zkRandContract.getIndexPlus(this.options.l2Wallet.address) - const cmdEval = `RUST_LOG=info ./target/release/client rand eval ${index} "${input}"` - const cmdVerify = `RUST_LOG=info ./target/release/client rand verify ${index} "${input}"` + const cmdEval = `${this.cmdPrefix} rand eval ${index} "${input}"` + const cmdVerify = `${this.cmdPrefix} rand verify ${index} "${input}"` console.log("running command <", cmdEval, ">...") let result = await execPromise(cmdEval) From e33990108cefd3ac71ce1dabf18c4c60526f4e9f Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Mon, 29 Jul 2024 10:40:43 +0100 Subject: [PATCH 4/8] remove axel --- ops/docker/Dockerfile.admin | 4 +--- ops/docker/Dockerfile.init | 5 +---- ops/docker/Dockerfile.node | 6 +----- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/ops/docker/Dockerfile.admin b/ops/docker/Dockerfile.admin index c7dea50..879ec4e 100644 --- a/ops/docker/Dockerfile.admin +++ b/ops/docker/Dockerfile.admin @@ -7,8 +7,7 @@ RUN apt-get update && apt-get install -y curl \ RUN apt-get install -y \ llvm \ clang \ - libclang-dev \ - axel + libclang-dev ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib @@ -30,7 +29,6 @@ COPY ./src ./src ENV PATH="/root/.cargo/bin:${PATH}" RUN cargo build --release -COPY ./data ./data # Declare the directory as a volume VOLUME /app/data diff --git a/ops/docker/Dockerfile.init b/ops/docker/Dockerfile.init index d5f59f6..ef4020b 100644 --- a/ops/docker/Dockerfile.init +++ b/ops/docker/Dockerfile.init @@ -7,8 +7,7 @@ RUN apt-get update && apt-get install -y curl \ RUN apt-get install -y \ llvm \ clang \ - libclang-dev \ - axel + libclang-dev ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib @@ -23,8 +22,6 @@ COPY ./src ./src ENV PATH="/root/.cargo/bin:${PATH}" RUN cargo build --release -COPY ./data ./data - # Declare the directory as a volume VOLUME /app/kzg_params diff --git a/ops/docker/Dockerfile.node b/ops/docker/Dockerfile.node index e06c4e5..c3ea215 100644 --- a/ops/docker/Dockerfile.node +++ b/ops/docker/Dockerfile.node @@ -7,8 +7,7 @@ RUN apt-get update && apt-get install -y curl \ RUN apt-get install -y \ llvm \ clang \ - libclang-dev \ - axel + libclang-dev ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib @@ -32,9 +31,6 @@ RUN cargo build --release # Declare the directory as a volume VOLUME /app/kzg_params - -# Declare the directory as a volume -COPY ./data ./data VOLUME /app/data COPY entrypoint.sh ./entrypoint.sh From c796abced89a968a2b1d9d6c7846e0def6797ea6 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Mon, 29 Jul 2024 14:16:56 +0100 Subject: [PATCH 5/8] fix minor errors --- docker-compose.yml | 23 +++++------------------ services/admin.ts | 4 ++-- services/node.ts | 6 +++--- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0a1aca0..0affb0f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,12 +10,6 @@ services: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 - DEGREE=18 - healthcheck: - test: [ "CMD", "test", "-f", "/app/kzg_params/health_check_3_5_18" ] - interval: 1m - timeout: 10s - retries: 10 - start_period: 10m admin: build: @@ -48,7 +42,6 @@ services: volumes: - kzg_params_volume:/app/kzg_params - node_1_volume:/app/data - entrypoint: [ "" ] environment: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 @@ -59,9 +52,8 @@ services: - NODE_PRIVATE_KEY=0x2e978a5709ac0dc3cbc2260519f8fcf5542af54dfaff489bcb4a69182be49429 depends_on: init: - condition: service_healthy + condition: service_completed_successfully - node-two: build: context: . @@ -70,7 +62,6 @@ services: volumes: - kzg_params_volume:/app/kzg_params - node_2_volume:/app/data - entrypoint: [ "" ] environment: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 @@ -81,7 +72,7 @@ services: - NODE_PRIVATE_KEY=0xa0a98d2341d78ed222b7a6314c026d8e85185203fd295f67b7146be956a05c58 depends_on: init: - condition: service_healthy + condition: service_completed_successfully node-three: build: @@ -91,7 +82,6 @@ services: volumes: - kzg_params_volume:/app/kzg_params - node_3_volume:/app/data - entrypoint: [ "" ] environment: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 @@ -102,7 +92,7 @@ services: - NODE_PRIVATE_KEY=0x742e271d909d026b2b4dcc0384ec0b8df8f674f0773c354b57c24858419e89d3 depends_on: init: - condition: service_healthy + condition: service_completed_successfully node-four: @@ -113,7 +103,6 @@ services: volumes: - kzg_params_volume:/app/kzg_params - node_4_volume:/app/data - entrypoint: [ "" ] environment: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 @@ -124,8 +113,7 @@ services: - NODE_PRIVATE_KEY=0xeeb82181766c7d0fe45d2cb5b3399b1da17a1a432938ec8c4d73daca85eedaea depends_on: init: - condition: service_healthy - + condition: service_completed_successfully node-five: build: @@ -135,7 +123,6 @@ services: volumes: - kzg_params_volume:/app/kzg_params - node_5_volume:/app/data - entrypoint: [ "" ] environment: - THRESHOLD=3 - NUMBER_OF_MEMBERS=5 @@ -146,7 +133,7 @@ services: - NODE_PRIVATE_KEY=0x88b68d7e8d96d8465cfe3dc4abf707e21aa49139189a784e2d50cc9ada9076c3 depends_on: init: - condition: service_healthy + condition: service_completed_successfully volumes: diff --git a/services/admin.ts b/services/admin.ts index b79b14d..17ccae8 100644 --- a/services/admin.ts +++ b/services/admin.ts @@ -233,7 +233,7 @@ export class AdminZkRandService extends BaseService { await waitForWriteJsonToFile(obj, instancesPath) console.log("retrieved all instances from contract") console.log("sleeping..") - await sleep(2000) + await sleep(5000) // derive global public parameters const cmd = `${this.cmdPrefix} dkg derive` @@ -299,7 +299,7 @@ export class AdminZkRandService extends BaseService { await waitForWriteJsonToFile(obj, instancesPath) console.log("retrieved all instances from contract") console.log("sleeping..") - await sleep(2000) + await sleep(5000) // derive global public parameters const cmd = `${this.cmdPrefix} dkg derive` diff --git a/services/node.ts b/services/node.ts index 8c0fe0f..87a3777 100644 --- a/services/node.ts +++ b/services/node.ts @@ -192,7 +192,7 @@ export class NodeZkRandService extends BaseService { const obj = JSON.stringify(ppListHex) await waitForWriteJsonToFile(obj, instancesPath) console.log("sleeping..") - await sleep(1000) + await sleep(5000) // each member derives its own secret share and global public parameters const cmd = `${this.cmdPrefix} dkg derive` @@ -211,7 +211,7 @@ export class NodeZkRandService extends BaseService { const obj = JSON.stringify(pks); await waitForWriteJsonToFile(obj, mpksPath); console.log("sleeping..") - await sleep(1000) + await sleep(2000) const index = await this.state.zkRandContract.getIndexPlus(this.options.l2Wallet.address) const cmdProve = `${this.cmdPrefix} dkg prove ${index}` @@ -250,7 +250,7 @@ export class NodeZkRandService extends BaseService { const obj = JSON.stringify(ppListHex) await waitForWriteJsonToFile(obj, instancesPath) console.log("sleeping..") - await sleep(2000) + await sleep(5000) // each member derives its own secret share and global public parameters const cmd = `${this.cmdPrefix} dkg derive` From 2f2f1ca2805909c3a1e04ee453cd060ef02e8d1b Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Tue, 30 Jul 2024 14:56:52 +0100 Subject: [PATCH 6/8] split rust/node build stages --- entrypoint.sh | 6 +-- ops/docker/Dockerfile.admin | 67 ++++++++++++++++++++++++---------- ops/docker/Dockerfile.init | 37 ++++++++++++++----- ops/docker/Dockerfile.node | 73 ++++++++++++++++++++++++++----------- services/admin.ts | 2 +- services/node.ts | 2 +- 6 files changed, 129 insertions(+), 58 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 08f6268..2267a7a 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -uex -echo "THRESHOLD: ${THRESHOLD}" -echo "NUMBER_OF_MEMBERS: ${NUMBER_OF_MEMBERS}" -echo "DEGREE: ${DEGREE}" +echo "(THRESHOLD, NUMBER_OF_MEMBERS, DEGREE) = (${THRESHOLD}, ${NUMBER_OF_MEMBERS}, ${DEGREE})" params_dir="kzg_params" degree_output_file="$params_dir/params${DEGREE}" @@ -23,7 +21,7 @@ else fi fi -RUST_LOG=info THRESHOLD=$THRESHOLD NUMBER_OF_MEMBERS=$NUMBER_OF_MEMBERS DEGREE=$DEGREE ./target/release/client setup --skip +RUST_LOG=info THRESHOLD=$THRESHOLD NUMBER_OF_MEMBERS=$NUMBER_OF_MEMBERS DEGREE=$DEGREE /usr/local/bin/client setup --skip # Touch a health check file to indicate readiness touch "$params_dir/health_check_${THRESHOLD}_${NUMBER_OF_MEMBERS}_${DEGREE}" diff --git a/ops/docker/Dockerfile.admin b/ops/docker/Dockerfile.admin index 879ec4e..f75c5e1 100644 --- a/ops/docker/Dockerfile.admin +++ b/ops/docker/Dockerfile.admin @@ -1,37 +1,64 @@ -FROM node:20 +# Stage 1: Build Stage +FROM rust:1.80 AS rust-builder -RUN apt-get update && apt-get install -y curl \ - && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ - && echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> $HOME/.bashrc - -RUN apt-get install -y \ +# Install necessary build dependencies +RUN apt-get update && apt-get install -y \ llvm \ clang \ - libclang-dev + libclang-dev \ + && rm -rf /var/lib/apt/lists/* +# Set environment variables for Rust ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib -# Create a working directory +# Create a working directory for Rust build WORKDIR /app -COPY ./package.json . +# Copy Rust source code and build configuration files +COPY ./Cargo.toml ./Cargo.lock ./ +COPY ./bin ./bin +COPY ./benches ./benches +COPY ./src ./src + +# Fetch dependencies and build the Rust project +RUN cargo fetch && cargo build --release + + +# Stage 2: Node Build Stage +FROM node:20 AS node-builder + +# Create a working directory for Node build +WORKDIR /app + +# Copy Node.js project files and install dependencies +COPY ./package.json ./ RUN yarn install +# Copy the rest of the Node.js application source COPY ./contracts ./contracts -COPY ./hardhat.config.ts . +COPY ./hardhat.config.ts ./ RUN yarn run build -COPY ./Cargo.toml . -COPY ./Cargo.lock . -COPY ./bin ./bin -COPY ./benches ./benches -COPY ./src ./src -ENV PATH="/root/.cargo/bin:${PATH}" -RUN cargo build --release +COPY ./tsconfig.json . +COPY ./services ./services + +# Stage 3: Runtime Stage +FROM node:20 AS runtime + +# Install runtime dependencies if needed (e.g., curl) +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Create working directory +WORKDIR /app # Declare the directory as a volume VOLUME /app/data -COPY ./tsconfig.json . -COPY ./services ./services -CMD ["yarn", "run", "services:admin"] +# Copy the built Rust binary and Node.js artifacts +COPY --from=node-builder /app /app +COPY --from=rust-builder /app/target/release/client /usr/local/bin/client + +# Set the entrypoint or default command +CMD ["yarn", "run", "services:admin"] \ No newline at end of file diff --git a/ops/docker/Dockerfile.init b/ops/docker/Dockerfile.init index ef4020b..0992466 100644 --- a/ops/docker/Dockerfile.init +++ b/ops/docker/Dockerfile.init @@ -1,31 +1,48 @@ -FROM node:20 +# Stage 1: Builder Stage +FROM rust:1.80 as builder -RUN apt-get update && apt-get install -y curl \ - && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ - && echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> $HOME/.bashrc - -RUN apt-get install -y \ +# Install necessary dependencies +RUN apt-get update && apt-get install -y \ llvm \ clang \ - libclang-dev + libclang-dev \ + curl \ + && rm -rf /var/lib/apt/lists/* +# Set environment variables for Rust ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib # Create a working directory WORKDIR /app -COPY ./Cargo.toml . -COPY ./Cargo.lock . +# Copy Rust source code and build configuration files +COPY ./Cargo.toml ./Cargo.lock ./ COPY ./bin ./bin COPY ./benches ./benches COPY ./src ./src -ENV PATH="/root/.cargo/bin:${PATH}" + +# Fetch dependencies and build the Rust project +RUN cargo fetch RUN cargo build --release +# Stage 2: Runtime Stage +FROM debian:buster-slim + +# Install curl for file downloading +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* + +# Copy the compiled Rust binary from the builder stage +COPY --from=builder /app/target/release/client /usr/local/bin/client + +# Create a working directory for runtime +WORKDIR /app + # Declare the directory as a volume VOLUME /app/kzg_params +# Copy the entrypoint script COPY entrypoint.sh ./entrypoint.sh RUN chmod +x ./entrypoint.sh +# Set the entrypoint ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/ops/docker/Dockerfile.node b/ops/docker/Dockerfile.node index c3ea215..06a78ae 100644 --- a/ops/docker/Dockerfile.node +++ b/ops/docker/Dockerfile.node @@ -1,42 +1,71 @@ -FROM node:20 +# Stage 1: Build Stage for Rust +FROM rust:1.80 AS rust-builder -RUN apt-get update && apt-get install -y curl \ - && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ - && echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> $HOME/.bashrc - -RUN apt-get install -y \ +# Install necessary build dependencies +RUN apt-get update && apt-get install -y \ llvm \ clang \ - libclang-dev + libclang-dev \ + && rm -rf /var/lib/apt/lists/* +# Set environment variables for Rust ENV LIBCLANG_PATH=/usr/lib/llvm-14/lib -# Create a working directory +# Create a working directory for Rust build WORKDIR /app -COPY ./package.json . +# Copy Rust source code and build configuration files +COPY ./Cargo.toml ./Cargo.lock ./ +COPY ./bin ./bin +COPY ./benches ./benches +COPY ./src ./src + +# Fetch dependencies and build the Rust project +RUN cargo fetch && cargo build --release + + +# Stage 2: Node Build Stage +FROM node:20 AS node-builder + +# Create a working directory for Node build +WORKDIR /app + +# Copy Node.js project files and install dependencies +COPY ./package.json ./ RUN yarn install +# Copy the rest of the Node.js application source COPY ./contracts ./contracts -COPY ./hardhat.config.ts . +COPY ./hardhat.config.ts ./ RUN yarn run build -COPY ./Cargo.toml . -COPY ./Cargo.lock . -COPY ./bin ./bin -COPY ./benches ./benches -COPY ./src ./src -ENV PATH="/root/.cargo/bin:${PATH}" -RUN cargo build --release +COPY ./tsconfig.json . +COPY ./services ./services +COPY entrypoint.sh ./entrypoint.sh + + +# Stage 3: Runtime Stage +FROM node:20 AS runtime + +# Install runtime dependencies if needed (e.g., curl) +RUN apt-get update && apt-get install -y \ + curl \ + && rm -rf /var/lib/apt/lists/* -# Declare the directory as a volume +# Create working directory +WORKDIR /app + +# Declare the directories as volumes VOLUME /app/kzg_params VOLUME /app/data -COPY entrypoint.sh ./entrypoint.sh +# Copy the built Rust binary +COPY --from=node-builder /app /app +COPY --from=rust-builder /app/target/release/client /usr/local/bin/client + +# Set executable permissions for the entrypoint script RUN chmod +x ./entrypoint.sh ENTRYPOINT ["./entrypoint.sh"] -COPY ./tsconfig.json . -COPY ./services ./services -CMD ["yarn", "run", "services:node"] +# Set the entrypoint or default command +CMD ["yarn", "run", "services:node"] \ No newline at end of file diff --git a/services/admin.ts b/services/admin.ts index 17ccae8..a7d1a57 100644 --- a/services/admin.ts +++ b/services/admin.ts @@ -102,7 +102,7 @@ export class AdminZkRandService extends BaseService { this.state.startDate = startDate.getTime() } - this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} ./target/release/client` + this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} /usr/local/bin/client` await this.check_config() } diff --git a/services/node.ts b/services/node.ts index 87a3777..1645160 100644 --- a/services/node.ts +++ b/services/node.ts @@ -78,7 +78,7 @@ export class NodeZkRandService extends BaseService { this.state.gasOverride = {gasLimit: 10000000} - this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} ./target/release/client` + this.cmdPrefix = `RUST_LOG=info THRESHOLD=${this.options.threshold} NUMBER_OF_MEMBERS=${this.options.numberMembers} DEGREE=${this.options.degree} /usr/local/bin/client` await this.check_config() } From 397cdd5a1721e493ca2a7f7886740d21eb92daba Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Tue, 30 Jul 2024 14:59:42 +0100 Subject: [PATCH 7/8] remove ./data --- data/config.toml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 data/config.toml diff --git a/data/config.toml b/data/config.toml deleted file mode 100644 index a27605a..0000000 --- a/data/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -threshold = 3 -number_of_members = 5 -degree = 18 \ No newline at end of file From 11febf64757415711c2dc48395a733b7cdada266 Mon Sep 17 00:00:00 2001 From: Jia Liu Date: Tue, 30 Jul 2024 16:47:27 +0100 Subject: [PATCH 8/8] fix lib error --- docker-compose.yml | 1 + ops/docker/Dockerfile.init | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0affb0f..7caacf6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: build: context: . dockerfile: ops/docker/Dockerfile.init + container_name: zkrand_init volumes: - kzg_params_volume:/app/kzg_params restart: "no" # Prevent restart after completion diff --git a/ops/docker/Dockerfile.init b/ops/docker/Dockerfile.init index 0992466..e119f4f 100644 --- a/ops/docker/Dockerfile.init +++ b/ops/docker/Dockerfile.init @@ -26,7 +26,7 @@ RUN cargo fetch RUN cargo build --release # Stage 2: Runtime Stage -FROM debian:buster-slim +FROM ubuntu:22.04 # Install curl for file downloading RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*