diff --git a/src/python.rs b/src/python.rs index 39b13bcdf..eacf56dc9 100644 --- a/src/python.rs +++ b/src/python.rs @@ -1491,7 +1491,7 @@ fn encode_evm_calldata<'a>( /// The path to the SRS file /// /// render_vk_separately: bool -/// Whether the verifier key should be rendered as a separate contract. We recommend disabling selector compression if this is enabled. To save the verifier key as a separate contract, set this to true and then call the create-evm-vk command +/// Whether the verifier key should be rendered as a separate contract. We recommend disabling selector compression if this is enabled. To save the verifier key as a separate contract, set this to true and then call the create_evm_vk command /// /// Returns /// ------- @@ -1533,6 +1533,56 @@ fn create_evm_verifier( }) } +/// Creates an Evm verifer key. This command should be called after create_evm_verifier with the render_vk_separately arg set to true. By rendering a verification key separately you can reuse the same verifier for similar circuit setups with different verifying keys, helping to reduce the amount of state our verifiers store on the blockchain. +/// +/// Arguments +/// --------- +/// vk_path: str +/// The path to the verification key file +/// +/// settings_path: str +/// The path to the settings file +/// +/// sol_code_path: str +/// The path to the create the solidity verifying key. +/// +/// abi_path: str +/// The path to create the ABI for the solidity verifier +/// +/// srs_path: str +/// The path to the SRS file +/// +/// Returns +/// ------- +/// bool +/// +#[pyfunction(signature = ( + vk_path=PathBuf::from(DEFAULT_VK), + settings_path=PathBuf::from(DEFAULT_SETTINGS), + sol_code_path=PathBuf::from(DEFAULT_VK_SOL), + abi_path=PathBuf::from(DEFAULT_VERIFIER_ABI), + srs_path=None +))] +fn create_evm_vk( + py: Python, + vk_path: PathBuf, + settings_path: PathBuf, + sol_code_path: PathBuf, + abi_path: PathBuf, + srs_path: Option, +) -> PyResult> { + pyo3_asyncio::tokio::future_into_py(py, async move { + crate::execute::create_evm_vk(vk_path, srs_path, settings_path, sol_code_path, abi_path) + .await + .map_err(|e| { + let err_str = format!("Failed to run create_evm_verifier: {}", e); + PyRuntimeError::new_err(err_str) + })?; + + Ok(true) + }) +} + /// Creates an EVM compatible data attestation verifier, you will need solc installed in your environment to run this /// /// Arguments @@ -1762,7 +1812,7 @@ fn deploy_da_evm( /// Arguments /// --------- /// addr_verifier: str -/// The path to verifier contract's address +/// The verifier contract's address as a hex string /// /// proof_path: str /// The path to the proof file (generated using the prove command) @@ -1774,7 +1824,7 @@ fn deploy_da_evm( /// does the verifier use data attestation ? /// /// addr_vk: str -/// +/// The addess of the separate VK contract (if the verifier key is rendered as a separate contract) /// Returns /// ------- /// bool @@ -1925,6 +1975,7 @@ fn ezkl(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(compile_circuit, m)?)?; m.add_function(wrap_pyfunction!(verify_aggr, m)?)?; m.add_function(wrap_pyfunction!(create_evm_verifier, m)?)?; + m.add_function(wrap_pyfunction!(create_evm_vk, m)?)?; m.add_function(wrap_pyfunction!(deploy_evm, m)?)?; m.add_function(wrap_pyfunction!(deploy_vk_evm, m)?)?; m.add_function(wrap_pyfunction!(deploy_da_evm, m)?)?; diff --git a/tests/python/binding_tests.py b/tests/python/binding_tests.py index 8cd8de61b..a00b0d891 100644 --- a/tests/python/binding_tests.py +++ b/tests/python/binding_tests.py @@ -423,6 +423,74 @@ async def test_create_evm_verifier(): assert res == True assert os.path.isfile(sol_code_path) +async def test_create_evm_verifier_separate_vk(): + """ + Create EVM a verifier with solidity code and separate vk + In order to run this test you will need to install solc in your environment + """ + vk_path = os.path.join(folder_path, 'test_evm.vk') + settings_path = os.path.join(folder_path, 'settings.json') + sol_code_path = os.path.join(folder_path, 'test_separate.sol') + vk_code_path = os.path.join(folder_path, 'test_vk.sol') + abi_path = os.path.join(folder_path, 'test_separate.abi') + abi_vk_path = os.path.join(folder_path, 'test_vk_separate.abi') + proof_path = os.path.join(folder_path, 'test_evm.pf') + calldata_path = os.path.join(folder_path, 'calldata.bytes') + + # # res is now a vector of bytes + # res = ezkl.encode_evm_calldata(proof_path, calldata_path) + + # assert os.path.isfile(calldata_path) + # assert len(res) > 0 + + + res = await ezkl.create_evm_verifier( + vk_path, + settings_path, + sol_code_path, + abi_path, + srs_path=srs_path, + render_vk_seperately=True + ) + + res = await ezkl.create_evm_vk( + vk_path, + settings_path, + vk_code_path, + abi_vk_path, + srs_path=srs_path, + ) + + assert res == True + assert os.path.isfile(sol_code_path) + + +async def test_deploy_evm_separate_vk(): + """ + Test deployment of the separate verifier smart contract + vk + In order to run this you will need to install solc in your environment + """ + addr_path_verifier = os.path.join(folder_path, 'address_separate.json') + addr_path_vk = os.path.join(folder_path, 'address_vk.json') + sol_code_path = os.path.join(folder_path, 'test_separate.sol') + vk_code_path = os.path.join(folder_path, 'test_vk.sol') + + # TODO: without optimization there will be out of gas errors + # sol_code_path = os.path.join(folder_path, 'test.sol') + + res = await ezkl.deploy_evm( + addr_path_verifier, + sol_code_path, + rpc_url=anvil_url, + ) + + res = await ezkl.deploy_vk_evm( + addr_path_vk, + vk_code_path, + rpc_url=anvil_url, + ) + + assert res == True async def test_deploy_evm(): """ @@ -503,6 +571,47 @@ async def test_verify_evm(): assert res == True +async def test_verify_evm_separate_vk(): + """ + Verifies an evm proof + In order to run this you will need to install solc in your environment + """ + proof_path = os.path.join(folder_path, 'test_evm.pf') + addr_path_verifier = os.path.join(folder_path, 'address_separate.json') + addr_path_vk = os.path.join(folder_path, 'address_vk.json') + proof_path = os.path.join(folder_path, 'test_evm.pf') + calldata_path = os.path.join(folder_path, 'calldata_separate.bytes') + + with open(addr_path_verifier, 'r') as file: + addr_verifier = file.read().rstrip() + + print(addr_verifier) + + with open(addr_path_vk, 'r') as file: + addr_vk = file.read().rstrip() + + print(addr_vk) + + # res is now a vector of bytes + res = ezkl.encode_evm_calldata(proof_path, calldata_path, addr_vk=addr_vk) + + assert os.path.isfile(calldata_path) + assert len(res) > 0 + + # TODO: without optimization there will be out of gas errors + # sol_code_path = os.path.join(folder_path, 'test.sol') + + res = await ezkl.verify_evm( + addr_verifier, + proof_path, + rpc_url=anvil_url, + addr_vk=addr_vk, + # sol_code_path + # optimizer_runs + ) + + assert res == True + async def test_aggregate_and_verify_aggr(): data_path = os.path.join(