A method and system for verifying the functional correctness of the Circom compiler

By formally verifying the Circom compiler and utilizing a combination of time-step simulation and hypothesis learning verification techniques, the reliability problem of zero-knowledge proof compilers was solved, automated correctness checks of the compiler were achieved, and the security of blockchain applications was improved.

CN120045457BActive Publication Date: 2026-01-06TONGJI UNIV
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202510118352.5
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2025-01-24
Publication Date
2026-01-06
Estimated Expiration
2045-01-24

AI Technical Summary

Technical Problem

Existing zero-knowledge proof compilers lack formal verification, have potential vulnerabilities, and are difficult to guarantee the reliability and security of the compiler, especially with high verification complexity under the state space explosion problem.

Method used

A combined verification technique of time-step simulation and hypothesis learning is used to formally verify the Circom compiler. Through abstract syntax tree parsing, constraint and computation model extraction, and combined with the SMT solver CVC5, the consistency of the compilation output with the source file in terms of constraints and computation is checked.

Benefits of technology

It achieves automated compiler function correctness verification, improves compiler reliability and security, reduces the risk of error propagation, and ensures the security and reliability of blockchain applications.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN120045457B_ABST
    Figure CN120045457B_ABST
Patent Text Reader

Abstract

This invention provides a method and system for verifying the functional correctness of the Circom compiler, used to ensure the correctness of the compiler's compilation artifacts based on Circom source code and the source file in terms of constraint consistency and computational consistency. The method includes the following steps: S1, verifying the assembly functions called by the Circom compiler; S2, compiling the Circom source code; S3, extracting the abstract syntax tree (AST) of the Circom source code; S4, parsing the AST to extract the constraint model and computational model; S5, parsing the R1CS file to extract the constraint model of the compilation artifact; S6, extracting the computational model of the compilation artifact; S7, verifying the equivalence between the constraint model of the source code and the constraint model of the R1CS file; S8, verifying the equivalence between the computational models of the source code and the CPP file; S9, proving that the Circom compiler can correctly compile the Circom source file.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of software development technology, and specifically to a method and system for verifying the functional correctness of the Circom compiler. Background Technology

[0002] As the application scenarios of blockchain technology continue to expand, the use of zero-knowledge proof technology is also deepening to meet users' ever-increasing demands for privacy, security, and verifiability. Currently, in addition to manually generating zero-knowledge proof algorithms, developers can also use zero-knowledge proof compilers to automatically translate the zero-knowledge proof process or objective described in a high-level language into a general intermediate language, thereby simplifying the complexity of zero-knowledge proofs.

[0003] Zero-knowledge proof compilers are crucial tools for building and verifying zero-knowledge proof systems, and ensuring the reliability and security of these compilers is of paramount importance. However, while several zero-knowledge proof compilers, such as Circom, zk-SNARK, and zk-STARK, have been developed, their reliability verification theories remain incomplete. Only a few compilers, such as ZoKrates, have undergone formal verification. Almeida et al. designed a zero-knowledge proof compiler based on the Σ protocol, which allows the automatic conversion of the abstract description of the target to be proved into an executable implementation and automatically outputs a formal proof of the compiled protocol; however, it does not formally verify the correctness of the compiler's code implementation. Cairo, the first Turing-complete language for creating provable programs for general-purpose computation, is frequently used in zero-knowledge proofs. However, developers have only used testing methods to perform necessary tests on the compiler's correctness, without providing formal security guarantees. RISC Zero is a general-purpose computing platform for zero-knowledge verification based on zk-STARK and RISC-V microarchitecture. However, it does not use formal verification technology in its design and development, which may lead to potential vulnerabilities that could cause security risks, data leaks, and other problems.

[0004] Currently, significant progress has been made in formal verification of high-level language compilers in other fields. Bochmann et al. proposed a formal verification scheme for the correctness of Java bytecode compiler design, which covers all object-oriented features. Leroy et al. designed and developed the trustworthy compiler CompCert using formal verification methods. The correctness of this compiler from design to operation has been formally verified, effectively ensuring its functional reliability.

[0005] The formal verification precedents of high-level language compilers above demonstrate the feasibility of formally verifying zero-knowledge proof compilers. However, compared to the former, the verification work of zero-knowledge proof compilers is more complex. On the one hand, they need to possess basic functions such as syntax analysis and syntactic analysis; on the other hand, they require targeted design for security and privacy guarantees, involving expertise in cryptographic algorithms and protocol design. This significantly increases the complexity of zero-knowledge proof compiler design, making its verification process highly susceptible to the state space explosion problem. Regarding the state space explosion problem, scholars both domestically and internationally have conducted numerous studies in various fields. Berendsen et al. used time-step simulation theory to manually establish abstractions of some components of the Zeroconf protocol, achieving correctness verification under arbitrary number of terminal conditions. Lin et al. proposed a combinatorial verification framework that uses model learning algorithms to automatically construct abstractions, achieving efficient verification of event-logging automata models. Hanyue Chen et al. overcame the problem of combining time automata model learning algorithms with combinatorial verification frameworks, achieving an efficient verification algorithm for time-based systems. These solutions can also be applied to the verification process of zero-knowledge proof compilers.

[0006] Therefore, the urgent technical problem to be solved is: how to use time-step simulation, hypothesis learning and other combined verification techniques to propose an efficient formal verification algorithm for zero-knowledge proof compilers at the design level, expand the reliability verification theory of zero-knowledge proof compilers, and provide technical support for the formal proof work of both. Summary of the Invention

[0007] This invention is made to solve the above-mentioned problems, and aims to provide a method and system for verifying the functional correctness of the Circom compiler.

[0008] This invention provides a method for verifying the functional correctness of the Circom compiler, characterized by the following steps: Step S1, pre-verifying the correctness of each assembly function in the assembly function library called by the Circom compiler and forming corresponding formal specifications, denoted as the assembly function functional formal specifications; Step S2, compiling the Circom source code using the Circom compiler, and if successful, saving the resulting .sym, .dat, and json format R1CS files and CPP files; Step S3, extracting the abstract syntax tree from the Circom source code and storing it in json file format; Step S4, parsing the abstract syntax tree of the Circom source code, and extracting the constraint model and computation model corresponding to the Circom source code based on the grammatical semantics of the Circom language, denoted as the constraint model and computation model corresponding to the source code; Step S5, parsing the compiled R1CS file based on the .sym file, and extracting the constraint model corresponding to the compilation product, denoted as the constraint model corresponding to the R1CS file; Step S6, based on the assembly function functional formal specifications and the .sym file, verifying the correctness of each assembly function in the .dat file and CPP files; The .dat and CPP files are parsed to extract the computational models corresponding to the compiled products, denoted as the computational models corresponding to the .dat file and the CPP file, respectively. `element_dict` is used to store the mapping relationship of signals in the CPP file. Step S7: The constraint models corresponding to the source code and the constraint models corresponding to the R1CS file are connected using equivalence relations. After inversion, the CVC5 solver is used to solve the problem. If there is no solution, it indicates that the Circom compiler can guarantee the consistency of constraints between the compiled products and the source files. If there is a solution, i.e., a counterexample exists, it indicates that the Circom compiler has an error. Step S8: Based on `element_dict`, the equivalence between the computational models corresponding to the source code and the CPP file is verified using the SMT solver to form the target property. The CVC5 solver is used to solve the problem. If there is no solution, it indicates that the Circom compiler can guarantee the consistency of computation between the compiled products and the source files. If there is a solution, i.e., a counterexample exists, it indicates that the Circom compiler has an error. Step S9: If the solution results of S7 and S8 are both unsolvable, it indicates that the Circom compiler can correctly compile the Circom source files.

[0009] The method for verifying the correctness of Circom compiler functionality provided by this invention may also have the following features: Step S1 includes the following sub-steps: Step S1-1, for each function in fr.asm, write a corresponding verification script .ini file. The script content mainly includes verifying whether the function is correct and whether the register overflows, etc.; Step S1-2, start the symbolic execution process of Binsec. The execution result will return whether the currently verified function has an error. If there is an error, return a counterexample. If it is correct, return the number of execution paths and the execution time. Finally, summarize the correctly executed script content into a more concise specification for subsequent use.

[0010] The method for verifying the correctness of the Circom compiler function provided by this invention may also have the following features: Step S3 includes the following sub-steps: Step S3-1, analyze the file containing the main module declaration of the Circom source code, parse each syntax node, convert the syntax structure into an abstract syntax tree, and temporarily store it in memory in JSON format, annotating in detail the signal declaration, variable declaration, module declaration, expression type, branch structure, loop structure, main module declaration parameters, and other information; Step S3-2, store the abstract syntax tree in the form of a JSON file in a specified location on the hard disk.

[0011] The method for verifying the correctness of Circom compiler functionality provided by this invention may also have the following feature: In step S3, between step S3-1 and step S3-2, the following sub-step is also included: according to the include import relationship, the call relationship between Circom source code is recursively parsed, and all involved code files are converted into abstract syntax trees; the template and function nodes in the abstract syntax tree are extracted and added to the definitions list of the abstract syntax tree in sequence, thereby realizing the merging of the abstract syntax trees.

[0012] The method for verifying the correctness of the Circom compiler provided by this invention may also have the following features: Step S4 includes the following sub-steps: Step S4-1, read a JSON file from a specified location on the hard disk and load the abstract syntax tree information into memory; Step S4-2, analyze the main_component node in the abstract syntax tree and extract the id of the template corresponding to the main module and the parameter assignment list; Step S4-3, parse the parameter assignment list, calculate the value of the expression therein, and store each parameter assignment in array form according to the original order, denoted as the parameter assignment array; Step S4-4, according to the module id, in the definitions column... The corresponding template is located in the table and then parsed. Based on the parameter list described by the `args` node, corresponding variables are generated and assigned values ​​according to the parameter assignment array. In steps S4-5, each node in the `stmt` list of the parsed template is parsed. Based on the `Declaration` node, corresponding `var`, `signal`, and `component` variables are generated. Based on the `ConstraintEquality` node, an equality expression is formed and stored in the constraint expression set. Based on the `Substitution` node, values ​​are assigned to specified variables, if the lvalue type is... If the right-hand side is of type `var`, the rvalue expression is parsed and its value is updated accordingly. If the left-hand side is of type `signal`, the rvalue expression is modeled as an expression over a finite field, forming an equation with the `signal` variable, and the generated expression is stored in the set of calculated expressions. If the assignment operator is `AssignConstraintSignal`, the generated expression is also stored in the set of constraint expressions. If the left-hand side is of type `Component`, it indicates that the right-hand side is a template call statement. The corresponding `id` and parameter assignment list are extracted, and then the process returns to step S4-3, recursively parsing the expression. Based on the `While` node, the expression is first calculated... If the true value of the `cond` node is true, then each node in the loop body is parsed, and the true value of the `cond` node is checked again until it is false. Based on the `IfThenElse` node, the true value of the `cond` node is calculated first. If it is true, then the `if_case` child node is parsed. If it is false and the `else_case` child node exists, then the `else_case` is parsed. In steps S4-6, the elements in the constraint expression set are connected by conjunction to form the constraint model corresponding to the source code, and the elements in the calculation expression set are connected by conjunction to form the calculation model corresponding to the source code.

[0013] The method for verifying the correctness of the Circom compiler function provided by this invention may also have the following feature: Step S5 includes the following sub-steps: Step S5-1, read the .sym file from a specified location on the hard disk line by line, where each line stores the index information of a certain signal; Step S5-2, divide each line into four parts using commas as separators, where the first part represents the order in which the signal appears in the Circom source code, denoted as id. s The second part represents the order in which the signal appears in the witness file (ID). w The third part represents the ID of the component to which the signal belongs. c The fourth part represents the name of the signal in the source code, denoted as name. Based on this, the id is constructed. w A bidirectional mapping table between names; Step S5-3: Read the R1CS file stored in JSON format from the specified location on the hard disk row by row, and parse each element in the list stored in the Constraints node. Each element contains three child elements, denoted as A, B, and C, and each child element contains several ids. w With coefficient pairs, based on a bidirectional mapping table, according to id w Obtain the corresponding variable names, and based on these, convert A, B, and C into their corresponding linear expressions, denoted as a, b, and c respectively, and form constraints of the form a*b=c; in step S5-4, connect the constraints a*b=c using the conjunction relation to form the constraint model corresponding to the R1CS file.

[0014] The method for verifying the correctness of the Circom compiler provided by this invention may also have the following features: Step S6 includes the following sub-steps: Step S6-1, in the .dat file, binary constants are mapped to the required FrElements in the .cpp file in groups of 40 bytes from back to front; Step S6-2, in the .sym file, the text is parsed line by line, and the signal is mapped to the required FrElements in the .cpp file; Step S6-3, the assembly function is formally reduced using CVC5 to generate a certain finite field operation verification condition, which is used to subsequently ensure that the input operation result conforms to the given verification logic; Step Step S6-4 uses string matching to parse the .cpp file line by line, converting the operations involved in the file into verification conditions for operations over finite fields. Specific supported operations include: template creation and referencing; control flow code containing for, if, and while loops; support for addition, subtraction, multiplication, and division; support for finding the inverse in finite field operations; support for comparison operations such as 'Fr_eq', 'Fr_neq', 'Fr_gt', 'Fr_lt', 'Fr_geq', and 'Fr_leq'; and support for assignment and exponentiation operations. Finally, the generated series of constraints are stored in a list in SMT format.

[0015] The method for verifying the functional correctness of the Circom compiler provided by this invention may also have the following features: Step S8 includes the following sub-steps: Step S8-1, traverse the signal mapping table, convert each key-value pair into an equality constraint, and store the equality constraint in the input equality constraint set or the result equality constraint set according to whether the signal involved is an input signal; Step S8-2, connect the elements in the input equality constraint set using a conjunction relation to form input constraints, and connect the elements in the result equality constraint set using a conjunction relation to form result constraints; Step S8-3, invert the result constraints, and then connect them with the input constraints, the computational model corresponding to the source code, and the computational model corresponding to the CPP file using a conjunction relation to form the target property; Step S8-4, solve the target property using the CVC5 solver. If there is no solution, it indicates that the Circom compiler can guarantee the computational consistency between the compiled product and the source file. If there is a solution, i.e., there is a counterexample, it indicates that the Circom compiler has an error.

[0016] This invention also discloses a system for verifying the functional correctness of a Circom compiler, characterized by: an AST generation tool for extracting an abstract syntax tree from the Circom source code to be compiled and storing it in JSON file format; an AST parsing tool for parsing the abstract syntax tree and extracting the constraint model and computational model corresponding to the source code based on the syntax and semantics of the Circom language; a CPP parsing tool for extracting the computational model corresponding to the compilation output, and an element_dict for storing the mapping relationship of signals in the CPP file; finally, a string matching method is used to parse the .cpp file line by line, converting the operations involved in the file into SMT format operations. Verification conditions: The R1CS parsing tool reads an R1CS file stored in JSON format from a specified location on the hard drive and parses each element in the list stored in the Constraints node; the Circom and R1CS equivalence verification tool uses CVC5 to check the equivalence between the uncompiled Circom code and the SMT formulas formed by the compiled R1CS, thus verifying the equivalence between the Circom code and the R1CS file; the Circom and CPP equivalence verification tool uses CVC5 to check the equivalence between the uncompiled Circom code and the SMT formulas formed by the compiled CPP code, thus verifying the equivalence between the Circom code and the CPP file.

[0017] The role and effect of invention

[0018] The method and system for verifying the functional correctness of the Circom compiler according to this invention can ensure the correctness of the compiled output and the Circom source code in terms of constraint consistency and computational consistency, even in the absence of existing formal verification tools. This invention, through pre-verification and formal reduction generation of assembly functions, combined with the SMT solver CVC5 for equivalence verification of constraints and computational models, can effectively detect potential errors in the Circom compiler during the compilation process. Furthermore, this method automates the verification process while ensuring verification accuracy, reducing manual intervention and improving verification efficiency. Simultaneously, by combining multiple consistency verifications of the compiled output and source files, it significantly improves the security and reliability of blockchain infrastructure software, reduces the risk of error propagation, and thus provides a higher level of compiler functional correctness assurance for blockchain applications. Attached Figure Description

[0019] Figure 1 This is a structural block diagram of the Circom compiler functional correctness verification system in an embodiment of the present invention;

[0020] Figure 2This is a flowchart illustrating the method for verifying the functional correctness of the Circom compiler in an embodiment of the present invention. Detailed Implementation

[0021] To make the technical means, creative features, objectives and effects of this invention easy to understand, the following embodiments, in conjunction with the accompanying drawings, specifically illustrate the method and system for verifying the functional correctness of the Circom compiler.

[0022] Figure 1 This is a structural block diagram of the Circom compiler functional correctness verification system in an embodiment of the present invention.

[0023] like Figure 1 As shown, the Circom compiler functional correctness verification system 10 in this example includes an AST generation tool 11, an AST parsing tool 12, a CPP parsing tool 13, an R1CS parsing tool 14, a Circom and CPP equivalence verification tool 15, and a Circom and R1CS equivalence verification tool 16.

[0024] The AST generation tool 11 is used to extract the Abstract Syntax Tree (AST) from the Circom source code and store it in JSON file format, laying the foundation for subsequent syntax parsing and model extraction.

[0025] The AST parsing tool 12 is used to parse the Abstract Syntax Tree (AST). Based on the syntax and semantics of the Circom language, it extracts the corresponding constraint model and computation model from the source code, which facilitates the verification of the logical structure of the source code.

[0026] CPP parsing tool 13 is used to analyze the compiled CPP files, extract the computational models from the compilation artifacts, and generate element_dict to store the mapping relationship of signals in the CPP files. The tool parses the CPP files line by line through string matching, converting the operations into verifiable SMT format computational conditions.

[0027] R1CS parsing tool 14 is used to read R1CS files stored in JSON format from a specified location, parse the list of elements in the Constraints node one by one, extract constraint information, and help build the constraint model of the compiled product.

[0028] The Circom and R1CS equivalence verification tool 15 uses the CVC5 solver to perform equivalence checks on the SMT formulas formed by the Circom source code and the R1CS file, verifying the consistency of the constraint model before and after compilation, and ensuring the correct mapping between the Circom code and the R1CS file.

[0029] The Circom and CPP equivalence verification tool 16 uses the CVC5 solver to verify the equivalence of the SMT formulas formed by the Circom source code and the compiled CPP code, ensuring the consistency of the source code and the compiled CPP file in terms of computational logic, thereby confirming the correctness of the compiler's functions.

[0030] Figure 2 This is a flowchart illustrating the method for verifying the functional correctness of the Circom compiler in an embodiment of the present invention.

[0031] like Figure 2 As shown, the method for verifying the functional correctness of the Circom compiler in this embodiment is used to ensure the correctness of the compiled products and the Circom source code in terms of constraint consistency and computational consistency, and includes the following steps:

[0032] In this embodiment, the content of FrElement defined in Circom includes: the first 32 bits store the short type data of the data, denoted as shortVal; the middle 32 bits store the data type, denoted as type; and the last 256 bits store the long type data of the data, denoted as longVal.

[0033] Step S1: Verify the correctness of each assembly function in the assembly function library called by the Circom compiler, and form the corresponding formal specification, which is denoted as the assembly function functional formal specification.

[0034] Step S1-1: For each function in fr.asm, write a corresponding verification script .ini file. The script content mainly includes verifying whether the function is correct and whether there are constraints such as register overflow.

[0035] Step S1-2: Start the symbolic execution process of Binsec. The execution result will return whether the function being verified has an error. If there is an error, a counterexample will be returned. If it is correct, the number of execution paths and the execution time will be returned. Finally, the content of the correctly executed script will be summarized into a more concise specification for later use.

[0036] In this embodiment, we will take the following circom code Num2Bits(n) as an example for verification:

[0037]

[0038] The assembly functions involved in this Circom code are x86-64 assembly code under Linux, including assembly functions such as Fr_copy and Fr_add. Script files such as Fr_copy.ini and Fr_add.ini were written for each function, containing constraints that each function must satisfy. These were then verified using the Binsec tool. After obtaining correct verification results, each assembly function was abstracted into the following specification (taking Fr_add as an example):

[0039]

[0040] Step S2: Compile the Circom source code using the Circom compiler. If successful, save the resulting R1CS files (.sym, .dat, json format) and CPP files.

[0041] The compilation instructions are as follows:

[0042]

[0043] The meanings of each parameter are shown in the table below:

[0044] parameter meaning compiler_path Path to the Circom compiler --OX The automation level, X, can be 0, 1, or 2, where 00 represents no optimization. raw_path Storage path of the main component file in the Circom source code --primeprime_name Specify the large prime number to use; prime_name is usually bn128. --r1cs Specify output R1CS file --sym Specify output sym file --c Specify that the compiled executable file should be output in C++ format. --json Specify outputting R1CS files in JSON format. -ocase_temp_path Specify the output path of the compiled output as case_temp_path

[0045] In this embodiment, the instructions are specifically as follows:

[0046]

[0047] If compilation fails, it indicates a problem with the Circom source code, which must be corrected according to the compiler's prompts. If compilation succeeds, save the resulting .sym, .dat, and json format R1CS files and CPP files, and proceed to step S3.

[0048] Step S3: Extract the abstract syntax tree from the Circom source code and store it in JSON file format.

[0049] This step is achieved by calling the Astbuilder tool. The command format is as follows:

[0050]

[0051] The meanings of each parameter are shown in the table below:

[0052] parameter meaning astbuilder_path Path to Astbuilder raw_path Storage path of the main component file in the Circom source code json_path Abstract Syntax Tree Output Path

[0053] In this embodiment, the instructions are specifically as follows:

[0054]

[0055] Step S3-1: Analyze the file containing the main module declaration in the Circom source code, parse each syntax node, parse the Num2Bits.circom file, transform the syntax structure into an abstract syntax tree, and temporarily store it in memory in JSON format, annotating in detail the signal declarations, variable declarations, module declarations, expression types, branch structures, loop structures, main module declaration parameters, and other information.

[0056] Step S3-2: Store the abstract syntax tree as a JSON file in a specified location on the hard drive.

[0057] Step S4: Parse the abstract syntax tree of the Circom source code obtained in step S3. Based on the syntax and semantics of the Circom language, extract the constraint model and computation model corresponding to the Circom source code, and denot them as the constraint model and computation model corresponding to the source code.

[0058] Step S4-1: Read the JSON file from the specified location on the hard drive and load the abstract syntax tree information into memory.

[0059] The `. / temp_file / Num2Bits / ast.json` file is read, and its stored abstract syntax tree information is loaded into memory. Each template in the definitions list is traversed, and its information is stored in a dictionary structure `template_dic` using its name as an index. After this sub-step is completed, the information stored in `template_dic` is: ["Num2Bits":"..."].

[0060] Step S4-2: Analyze the main_component node in the abstract syntax tree and extract the id and parameter assignment list of the template corresponding to the main module.

[0061] Locate the `main_component` node in the abstract syntax tree. Its main content is as follows: The `id` information is "Num2Bits", and the main information of the parameter assignment list is:

[0062]

[0063] Step S4-3: Parse the parameter assignment list, calculate the value of the expression, and store the parameter assignments in array form according to the original order, denoted as the parameter assignment array.

[0064] Step S4-4: Find the corresponding template in the definitions list according to the module ID, parse it, generate corresponding variables based on the parameter list described by the args node, and assign values ​​according to the parameter assignment array.

[0065] In this embodiment, the corresponding information is extracted from template_dic according to the template id corresponding to the main module, namely Num2Bits. The information stored in the args node is ["n"], which generates var Num2Bits[0].n, and assigns it an initial value of 4 according to the parameter assignment list.

[0066] Steps S4-5 involve parsing each node in the stmt list of the parsed template. Based on the Declaration node, corresponding var, signal, and component variables are generated. Based on the ConstraintEquality node, an equality expression is formed and stored in the constraint expression set. Based on the Substitution node, a value is assigned to the specified variable. If the lvalue type is var, the rvalue expression is parsed and its value is obtained to update the var variable. If the lvalue type is signal, the rvalue expression is modeled as an expression over a finite field, forming an equality with the signal variable, and the generated expression is stored in the computation expression set. If the assignment operator is AssignCon... If `straintSignal` is used, the generated expression needs to be stored in the constraint expression set. If the lvalue type is `Component`, it indicates that the right side is a `template` call statement. Extract the corresponding `id` and parameter assignment list, and then return to step S4-3 to recursively parse it. Based on the `While` node, first calculate the truth value of the `cond` node. If it is true, parse each node in the loop body, and then check the truth value of the `cond` node again until it is false. Based on the `IfThenElse` node, first calculate the truth value of the `cond` node. If it is true, parse the `if_case` child node. If it is false and the `else_case` child node exists, parse the `else_case`.

[0067] In this embodiment, each node in the stmt list of the parsed template is parsed to generate the following parameters:

[0068]

[0069] This results in the following set of constraint expressions:

[0070]

[0071]

[0072] And form the following set of computational expressions:

[0073]

[0074] Steps S4-6 connect the elements in the constraint expression set using conjunction relations to form the constraint model corresponding to the source code.

[0075] In this embodiment, the constraint model is as follows:

[0076]

[0077]

[0078] The elements in the set of computational expressions are connected by conjunction to form the computational model corresponding to the source code.

[0079] In this embodiment, the specific calculation model is as follows:

[0080]

[0081] Step S5: Based on the .sym file, parse the compiled R1CS file and extract the constraint model corresponding to the compilation product, which is denoted as the constraint model corresponding to the R1CS file.

[0082] In this embodiment, the compiled Num2Bits_constraints.json is parsed based on the Num2Bits.sym file.

[0083] Step S5-1: Read the .sym file from the specified location on the hard disk line by line. Each line stores the index information of a certain signal.

[0084] In this embodiment, the Num2Bits.sym file is read into memory from the location . / temp_file / Num2Bits / Num2Bits.sym on the hard disk. Its contents are as follows:

[0085]

[0086] Step S5-2: Divide each line into four parts using commas as separators. The first part represents the order in which the signal appears in the Circom source code, denoted as id. s The second part represents the order in which the signal appears in the witness file (ID). wThe third part represents the ID of the component to which the signal belongs. c The fourth part represents the name of the signal in the source code, denoted as name. Based on this, the id is constructed. w A two-way mapping table between names and names.

[0087] In this embodiment, based on the above four parts, a SymDataDic object is generated, which contains the following five attributes, the contents of which are as follows:

[0088]

[0089] Step S5-3: Read the R1CS file stored in JSON format from the specified location on the hard drive line by line.

[0090] In this embodiment, the contents of Num2Bits_constraints.json are read from the location . / temp_file / Num2Bits / Num2Bits_constraints.json on the hard drive, and the information is as follows:

[0091]

[0092] The elements in the list stored in the Constraints node are parsed one by one. Each element contains three child elements, denoted as A, B, and C, and each child element contains several ids. w With coefficient pairs, based on a bidirectional mapping table, according to id w Obtain the corresponding variable names, and based on these, convert A, B, and C into their corresponding linear expressions, denoted as a, b, and c respectively, forming a constraint of the form a*b=c.

[0093] In this embodiment, the three sub-elements are:

[0094]

[0095] For the first child element, based on __w_dic_r in SymDataDic, "0" is #f1m21888242871839275222246405745257275088548364400416034343698204186575808495617, which is the identity element in the finite field defined by the large prime number bn128. The "1" to the left of the colon is 'main.out[0]'. Furthermore, according to __signal_dic in SymDataDic, 'main.out[0]' can be further mapped to Output signal Num2Bits[0].out[0]. "21888242871839275222246405745257275088548364400416034343698204186575808495616" is its coefficient, which is equivalent to -1 in the finite field. The "1" to the left of the colon is 1 in the finite field. Thus, the expression 1*-1+Num2Bits[0].out[0]*1 is formed.

[0096] Similarly, the second sub-element can be parsed to form the expression 1*1, and the third sub-element contains no content, so it forms the expression 0. Based on the expression formed by parsing the three sub-elements, the constraint is formed: (1*-1+Num2Bits[0].out[0]*1)+1=0.

[0097] Similarly, the remaining elements in constraints are parsed sequentially to form a constraint set, which is stored in memory as follows:

[0098]

[0099]

[0100] Step S5-4: Connect the constraints obtained in step 5-3 using conjunction relations to form the constraint model corresponding to the R1CS file.

[0101] Step S6: Based on the formal specification of assembly function functions and the .sym file, parse the .dat and CPP files, extract the computational models corresponding to the compilation products, and denot them as the computational model corresponding to the .dat file and the computational model corresponding to the CPP file, and use element_dict to store the mapping relationship of signal in the CPP file.

[0102] Step S6-1: In the Num2Bits.dat file, the binary constants are mapped to the required FrElements in the .cpp file in groups of 40 bytes from back to front. In this embodiment, constant 1 is used as an example, and it is stored in binary form in the Num2Bits.dat file.

[0103]

[0104] The first 32 bits store the short type data, the middle 32 bits store the data type, and the last 256 bits store the long type data. After being extracted in sequence, the data is saved as FrElement format data.

[0105] Step S6-2: Parse the text line by line in the .sym file and map the signal to the required FrElement in the .cpp file;

[0106] In this embodiment, the signal names and their corresponding numbers involved in the Num2Bits.sym file are stored in FrElement format, with the following content:

[0107]

[0108] Step S6-3: Using CVC5, the formal reduction of Fr_add prepared in S1-2 is used to generate operation verification conditions over a certain finite field, which are used to ensure that the input operation results conform to the given verification logic, as shown below:

[0109]

[0110]

[0111] Step S6-4: Use string matching to parse the Num2Bits.cpp file line by line, and convert the operations involved in the file into the operation verification conditions on the finite field prepared in step S6-3.

[0112] Specifically supported operations include: template creation and referencing; control flow code containing for, if, and while loops; support for addition, subtraction, multiplication, and division; support for finding the inverse in finite field operations; support for comparison operations such as 'Fr_eq', 'Fr_neq', 'Fr_gt', 'Fr_lt', 'Fr_geq', and 'Fr_leq'; and support for assignment and exponentiation operations. Finally, the generated series of constraints are stored in a list in SMT format.

[0113] In this embodiment, Num2Bits.circom involves a for loop operation, so the corresponding loop needs to be expanded when parsing the cpp file. In this embodiment, when encountering an operation such as Fr_add(&expaux[0],&lvar[1],&expaux[2]), the operation verification conditions on the finite field prepared in S6-3 are automatically applied (if other operations are encountered, the same logic is used). Finally, all the prepared operation verification conditions are stored in a list in SMT format, which is the calculation model corresponding to the cpp file.

[0114] Step S7: Connect the constraint model corresponding to the source code in step S4 and the constraint model corresponding to the R1CS file in step S5 using equivalence relations, invert them, and then use the CVC5 solver to solve them. If there is no solution, it means that the Circom compiler can guarantee the consistency of the constraints between the compiled product and the source file. If there is a solution, that is, there is a counterexample, it means that there is an error in the Circom compiler.

[0115] Step S8: Based on element_dict, the equivalence between the computational model corresponding to the source code and the computational model corresponding to the CPP file is verified using the SMT solver to form the target property. The CVC5 solver is used to solve the problem. If there is no solution, it indicates that the Circom compiler can guarantee the computational consistency between the compiled product and the source file. If there is a solution, that is, there is a counterexample, it indicates that there is an error in the Circom compiler.

[0116] Step S8-1: Traverse the signal mapping table, convert each key-value pair into an equality constraint, and store the equality constraint into the input equality constraint set or the result equality constraint set according to whether the signal involved is an input signal.

[0117] The resulting set of input equality constraints is as follows:

[0118]

[0119] The resulting set of equality constraints is as follows:

[0120]

[0121] Step S8-2: Connect the elements in the input equality constraint set using the conjunction relation to form the input constraints, and connect the elements in the result equality constraint set using the conjunction relation to form the result constraints.

[0122] Step S8-3: Invert the result constraints, and then use the conjunction relation to connect them with the input constraints, the computational model corresponding to the source code in step S4, and the computational model corresponding to the CPP file in step S6 to form the target property.

[0123] Step S8-4: Use the CVC5 solver to solve for the target property. If there is no solution, it means that the Circom compiler can guarantee the consistency between the compiled product and the source file. If there is a solution, that is, there is a counterexample, it means that there is an error in the Circom compiler.

[0124] Step S9: If the constraint consistency in step S7 and the computation consistency in step S8 are both guaranteed, it means that the Circom compiler can correctly compile the Circom source file and output "equivalent".

[0125] Example 2

[0126] In this embodiment, the sub-step in step S3 is replaced with:

[0127] Step S3-1: Analyze the file containing the main module declaration in the Circom source code, parse each syntax node, transform the syntax structure into an abstract syntax tree, and temporarily store it in memory in JSON format. Detailed annotations are provided for signal declarations, variable declarations, module declarations, expression types, branch structures, loop structures, main module declaration parameters, and other information.

[0128] Step S3-2: Based on the include import relationship, recursively parse the call relationship between the Circom source code, and convert all the code files involved into an abstract syntax tree.

[0129] Step S3-3: Extract the template and function nodes from the abstract syntax tree and add them to the definitions list of the abstract syntax tree in turn, thereby merging the abstract syntax trees.

[0130] Step S3-4: Store the abstract syntax tree as a JSON file in a specified location on the hard drive.

[0131] For ease of explanation, the same symbols are used for structures identical to those in Embodiment 1, and the same descriptions are omitted in this embodiment.

[0132] Those skilled in the art should understand that this invention is not limited to the above embodiments. The embodiments and descriptions in the specification are merely illustrative of the principles of the invention. Various changes and modifications can be made to this invention without departing from its spirit and scope, and all such changes and modifications fall within the scope of the invention as claimed. The scope of protection of this invention is defined by the appended claims and their equivalents.

Claims

1. A method for verifying the correctness of a Circom compiler, comprising: Comprises: Step S1, pre-verification for each assembly function in the assembly function library called by Circom compiler, verify the correctness of the function, and form the corresponding formal specification, denoted as assembly function formal specification; Step S2, using Circom compiler to compile Circom source code, if it can pass, save the sym,.dat, json format R1CS file and CPP file obtained by compiling; Step S3, extract the abstract syntax tree from the Circom source code, and store it in json file format; Step S4, parse the abstract syntax tree of the Circom source code, extract the constraint model and the calculation model corresponding to the Circom source code based on the syntax semantics of Circom language, denoted as the constraint model corresponding to the source code and the calculation model corresponding to the source code; Step S5, based on the.sym file, parse the R1CS file obtained by compiling, extract the constraint model corresponding to the compilation product, denoted as the constraint model corresponding to the R1CS file; Step S6, based on the assembly function formal specification and the.sym file, parse the.dat and CPP files, extract the calculation model corresponding to the compilation product, denoted as the calculation model corresponding to the.dat file and the calculation model corresponding to the CPP file, and element_dict is used to store the mapping relationship of signal in CPP file; Step S7, connect the constraint model corresponding to the source code and the constraint model corresponding to the R1CS file using the equivalence relation, and solve it using CVC5 solver after negation, if there is no solution, it indicates that Circom compiler can guarantee the constraint consistency of the compilation product and the source file, if there is a solution, that is, there is a counterexample, which indicates that there is an error in Circom compiler; Step S8, based on the element_dict, combine the SMT solver to verify the equivalence of the calculation model corresponding to the source code and the calculation model corresponding to the CPP file to form the target property, and use CVC5 solver to solve, if there is no solution, it indicates that Circom compiler can guarantee the calculation consistency of the compilation product and the source file, if there is a solution, that is, there is a counterexample, which indicates that there is an error in Circom compiler; Step S9, if the solving results of S7 and S8 are both no solution, it indicates that Circom compiler can correctly compile Circom source file.

2. The method for verifying the functional correctness of a Circom compiler according to claim 1, Its characteristics are: Among them, the step S1 includes the following sub steps: Step S1-1, for each function in fr.asm, write the corresponding verification script.ini file, the script content mainly includes whether the function function is correct, and whether the register is overflowed and other constraints; Step S1-2, start the symbolic execution process of Binsec, and return whether the current verified function has an error in the execution result. If there is an error, return an anti-example. If it is correct, return the number of execution paths and the execution time. Finally, summarize the correct execution script content into a more concise specification for subsequent use.

3. The method for verifying the functional correctness of a Circom compiler of claim 1, It is characterized in that: The step S3 comprises the following sub-steps: Step S3-1, analyze the file where the Circom source code main module declaration is located, parse each syntax node, convert the syntax structure into an abstract syntax tree, and temporarily store it in memory in json format, and mark the signal declaration, variable declaration, module declaration, expression type, branching structure, loop structure, main module declaration parameter and other information in detail; Step S3-2, store the abstract syntax tree in the form of a json file in a specified location on the hard disk.

4. The method for verifying the functional correctness of a Circom compiler of claim 3, It is characterized in that: In step S3, between step S3-1 and step S3-2, the following sub-steps are further included: According to the include import relationship, recursively parse the calling relationship among the Circom source codes, and convert all the involved code files into abstract syntax trees; Extract the template and function nodes in the abstract syntax tree and add them to the definitions list of the abstract syntax tree in turn, thereby realizing the merging of the abstract syntax tree.

5. The method for verifying the functional correctness of a Circom compiler of claim 1, It is characterized in that: The step S4 comprises the following sub-steps: Step S4-1, read the json file from the specified location on the hard disk, and load the abstract syntax tree information into the memory; Step S4-2, analyze the main_component node in the abstract syntax tree, and extract the id of the template corresponding to the main module and the parameter assignment list; Step S4-3, parse the parameter assignment list, calculate the value of the expression therein, and store each parameter assignment in array form in accordance with the original order, denoted as the parameter assignment array; Step S4-4, find the corresponding template in the definitions list according to the module id, then parse it, generate the corresponding variable based on the parameter list described in the args node, and assign values according to the parameter assignment array; Step S4-5, parsing each node in the stmt list of the parsed template, based on the Declaration node therein, generating corresponding var variables, signal variables and component variables, based on the ConstraintEquality node therein, forming an equation expression and storing it in the constraint expression set, based on the Substitution node therein, assigning values to specified variables, if the left value type is var, parsing the right value expression to obtain a value, thereby updating the var variable; if the left value type is signal, modeling the right value expression into an expression on a finite field, forming an equation with the signal variable, and storing the generated expression in the calculation expression set, if the assignment operator is AssignConstraintSignal, also storing the generated expression in the constraint expression set; if the left value type is Component, indicating that the right side is a template call statement, extracting the corresponding id and parameter assignment list, and then returning to step S4-3 for recursive parsing, based on the While node therein, first calculating the truth value of the cond node, if true, parsing each node in the loop body, and then checking the truth value of the cond node again until it is false, based on the IfThenElse node therein, first calculating the truth value of the cond node, if true, parsing the if_case child node, if false and the else_case child node exists, parsing the else_case; Step S4-6, connecting each element in the constraint expression set with a conjunction relation to form a constraint model corresponding to the source code, and connecting each element in the calculation expression set with a conjunction relation to form a calculation model corresponding to the source code.

6. The method for verifying the functional correctness of a Circom compiler of claim 1, Characterized in that: The step S5 includes the following sub-steps: Step S5-1, reading the.sym file from the specified location on the hard disk by line, each line storing the index information of a signal; Step S5-2, divide each line into 4 parts with English comma as the delimiter, wherein the first part represents the occurrence order of the signal in the Circom source code, denoted as id s , the second part represents the occurrence order of the signal in the witness file id w , the third part represents the number of the component to which the signal belongs id c , and the fourth part represents the name of the signal in the source code, denoted as name. On this basis, a bidirectional mapping relationship table between id w and name is constructed. Step S5-3, reading the R1CS file stored in json format from the specified location of the hard disk by row, parsing the elements in the list stored in the Constraints node one by one, wherein each element contains three sub-elements, denoted as A, B, and C respectively, and each sub-element contains a plurality of ids w According to the id w Obtaining the variable name corresponding thereto, and converting A, B, and C into corresponding first-order expressions a, b, and c respectively on this basis, and forming a constraint in the form of a*b=c. Step S5-4, connecting the constraints of a*b=c using a conjunction relation to form a constraint model corresponding to the R1CS file.

7. The method for verifying the functional correctness of a Circom compiler according to claim 1, characterized in that: wherein The step S6 includes the following sub-steps: Step S6-1, mapping binary constants to FrElement required in the.cpp file by group of 40 bytes from the back to the front in the.dat file; Step S6-2, parsing the text line by line in the.sym file to map signals to FrElement required in the.cpp file; Step S6-3, formalizing the function form of the assembly function using CVC5 to generate operation verification conditions on a finite field, which are used to ensure that the input operation result conforms to the given verification logic in the subsequent steps; Step S6-4, using string matching method to parse the.cpp file line by line, converting the operation involved in the file into the operation verification condition on the finite field, and supporting operations such as the creation and reference of template, the control flow code containing for, if and while, the support for four arithmetic operations of addition, subtraction, multiplication and division, the support for inverse element in finite field operation, the support for comparison operations such as 'Fr_eq', 'Fr_neq', 'Fr_gt', 'Fr_lt', 'Fr_geq', 'Fr_leq', and the support for assignment and power operation, and finally storing the generated series of constraint conditions in SMT format in a list.

8. The method for verifying the functional correctness of a Circom compiler of claim 1, It is characterized in that: The step S8 includes the following sub-steps: Step S8-1, traversing the signal mapping relationship table, converting each key-value pair in it into an equation constraint, and according to the involved signal being an input signal, storing the equation constraint in the input equation constraint set, and according to the involved signal not being an input signal, storing the equation constraint in the result equation constraint set; Step S8-2, using the conjunction relation to connect each element in the input equation constraint set to form an input constraint, and using the conjunction relation to connect each element in the result equation constraint set to form a result constraint; Step S8-3, negating the result constraint, and then using the conjunction relation to connect it with the input constraint, the calculation model corresponding to the source code and the calculation model corresponding to the CPP file to form a target property; Step S8-4, using the CVC5 solver to solve the target property, if there is no solution, it indicates that the Circom compiler can guarantee the calculation consistency of the compiled product and the source file, if there is a solution, that is, there is a counterexample, which indicates that there is an error in the Circom compiler.

9. A method system for verifying the functional correctness of a Circom compiler, comprising: It includes: An AST generation tool for extracting an abstract syntax tree from the Circom source code to be compiled and storing it in a json file format; An AST analysis tool for analyzing the abstract syntax tree, extracting the constraint model and calculation model corresponding to the source code based on the syntax semantics of the Circom language; A CPP analysis tool for extracting the calculation model corresponding to the compiled product, and an element_dict for storing the mapping relationship of signal in the.cpp file, and finally using the string matching method to parse the.cpp file line by line, converting the operation involved in the file into the operation verification condition in SMT format; An R1CS analysis tool for reading the R1CS file stored in json format from a specified location on the hard disk, and parsing each element in the list stored in the Constraints node one by one; Circom and R1CS equivalence verification tool, used to check the equivalence of the SMT formulas formed by the pre-compiled Circom code and the post-compiled R1CS respectively through CVC5, so as to verify the equivalence of the Circom code and the R1CS file; Circom and CPP equivalence verification tool, used to check the equivalence of the SMT formulas formed by the pre-compiled Circom code and the post-compiled CPP code respectively through CVC5, so as to verify the equivalence of the Circom code and the CPP file.

Citation Information

Patent Citations

  • Formal verification method of intelligent contract, electronic device and storage medium

    CN110532176A

  • Automatic form verification method and device based on constraint solver

    CN115268853A