Просмотр исходного кода

zkas: Write the circuit namespace in the bincode.

Luther Blissett 3 лет назад
Родитель
Сommit
c93034f164
5 измененных файлов с 43 добавлено и 7 удалено
  1. 2 1
      bin/zkas/src/main.rs
  2. 17 2
      doc/src/zkas/bincode.md
  3. 6 1
      src/zkas/compiler.rs
  4. 6 1
      src/zkas/decoder.rs
  5. 12 2
      src/zkas/parser.rs

+ 2 - 1
bin/zkas/src/main.rs

@@ -63,7 +63,7 @@ fn main() {
     // the initial AST, not caring much about the semantics, just enforcing
     // the initial AST, not caring much about the semantics, just enforcing
     // syntax and general structure.
     // syntax and general structure.
     let parser = Parser::new(filename, source.chars(), tokens);
     let parser = Parser::new(filename, source.chars(), tokens);
-    let (constants, witnesses, statements) = parser.parse();
+    let (namespace, constants, witnesses, statements) = parser.parse();
 
 
     // The analyzer goes through the initial AST provided by the parser and
     // The analyzer goes through the initial AST provided by the parser and
     // converts return and variable types to their correct forms, and also
     // converts return and variable types to their correct forms, and also
@@ -86,6 +86,7 @@ fn main() {
     let compiler = Compiler::new(
     let compiler = Compiler::new(
         filename,
         filename,
         source.chars(),
         source.chars(),
+        namespace,
         analyzer.constants,
         analyzer.constants,
         analyzer.witnesses,
         analyzer.witnesses,
         analyzer.statements,
         analyzer.statements,

+ 17 - 2
doc/src/zkas/bincode.md

@@ -18,6 +18,7 @@ The compiled binary blob has the following layout:
 ```
 ```
 MAGIC_BYTES
 MAGIC_BYTES
 BINARY_VERSION
 BINARY_VERSION
+NAMESPACE
 .constant
 .constant
 CONSTANT_TYPE CONSTANT_NAME 
 CONSTANT_TYPE CONSTANT_NAME 
 CONSTANT_TYPE CONSTANT_NAME 
 CONSTANT_TYPE CONSTANT_NAME 
@@ -39,8 +40,8 @@ TBD
 ```
 ```
 
 
 Integers in the binary are encoded using variable-integer encoding.
 Integers in the binary are encoded using variable-integer encoding.
-See [`serial.rs`](https://github.com/darkrenaissance/darkfi/blob/master/src/util/serial.rs)
-for our Rust implementation.
+See the [`serial`](https://github.com/darkrenaissance/darkfi/blob/master/src/serial/src/lib.rs)
+crate and module for our Rust implementation.
 
 
 ## Sections
 ## Sections
 
 
@@ -59,6 +60,20 @@ potential different formats in the future.
 
 
 > `0x02`
 > `0x02`
 
 
+### `NAMESPACE`
+
+This sector after `MAGIC_BYTES` and `BINARY_VERSION` contains the
+reference namespace of the code. This is the namespace used in the
+source code, e.g.:
+
+```
+constant "MyNamespace" { ... }
+contract "MyNamespace" { ... }
+circuit  "MyNamespace" { ... }
+```
+
+The string is serialized with variable-integer encoding.
+
 ### `.constant`
 ### `.constant`
 
 
 The constants in the `.constant` section are declared with their type
 The constants in the `.constant` section are declared with their type

+ 6 - 1
src/zkas/compiler.rs

@@ -14,6 +14,7 @@ pub const BINARY_VERSION: u8 = 2;
 pub const MAGIC_BYTES: [u8; 4] = [0x0b, 0x01, 0xb1, 0x35];
 pub const MAGIC_BYTES: [u8; 4] = [0x0b, 0x01, 0xb1, 0x35];
 
 
 pub struct Compiler {
 pub struct Compiler {
+    namespace: String,
     constants: Vec<Constant>,
     constants: Vec<Constant>,
     witnesses: Vec<Witness>,
     witnesses: Vec<Witness>,
     statements: Vec<Statement>,
     statements: Vec<Statement>,
@@ -26,6 +27,7 @@ impl Compiler {
     pub fn new(
     pub fn new(
         filename: &str,
         filename: &str,
         source: Chars,
         source: Chars,
+        namespace: String,
         constants: Vec<Constant>,
         constants: Vec<Constant>,
         witnesses: Vec<Witness>,
         witnesses: Vec<Witness>,
         statements: Vec<Statement>,
         statements: Vec<Statement>,
@@ -37,7 +39,7 @@ impl Compiler {
         let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
         let lines: Vec<String> = source.as_str().lines().map(|x| x.to_string()).collect();
         let error = ErrorEmitter::new("Compiler", filename, lines);
         let error = ErrorEmitter::new("Compiler", filename, lines);
 
 
-        Self { constants, witnesses, statements, literals, debug_info, error }
+        Self { namespace, constants, witnesses, statements, literals, debug_info, error }
     }
     }
 
 
     pub fn compile(&self) -> Vec<u8> {
     pub fn compile(&self) -> Vec<u8> {
@@ -47,6 +49,9 @@ impl Compiler {
         bincode.extend_from_slice(&MAGIC_BYTES);
         bincode.extend_from_slice(&MAGIC_BYTES);
         bincode.push(BINARY_VERSION);
         bincode.push(BINARY_VERSION);
 
 
+        // Write the circuit's namespace
+        bincode.extend_from_slice(&serialize(&self.namespace));
+
         // Temporaty stack vector for lookups
         // Temporaty stack vector for lookups
         let mut tmp_stack = vec![];
         let mut tmp_stack = vec![];
 
 

+ 6 - 1
src/zkas/decoder.rs

@@ -7,6 +7,7 @@ use crate::{Error::ZkasDecoderError as ZkasErr, Result};
 /// This is used by the zkvm.
 /// This is used by the zkvm.
 #[derive(Clone, Debug)]
 #[derive(Clone, Debug)]
 pub struct ZkBinary {
 pub struct ZkBinary {
+    pub namespace: String,
     pub constants: Vec<(VarType, String)>,
     pub constants: Vec<(VarType, String)>,
     pub literals: Vec<(LitType, String)>,
     pub literals: Vec<(LitType, String)>,
     pub witnesses: Vec<VarType>,
     pub witnesses: Vec<VarType>,
@@ -27,6 +28,9 @@ impl ZkBinary {
 
 
         let _binary_version = &bytes[4];
         let _binary_version = &bytes[4];
 
 
+        // After the binary version, we're supposed to have the contract namespace
+        let (namespace, _) = deserialize_partial(&bytes[5..])?;
+
         let constants_offset = match find_subslice(bytes, b".constant") {
         let constants_offset = match find_subslice(bytes, b".constant") {
             Some(v) => v,
             Some(v) => v,
             None => return Err(ZkasErr("Could not find .constant section".to_string())),
             None => return Err(ZkasErr("Could not find .constant section".to_string())),
@@ -77,9 +81,10 @@ impl ZkBinary {
         let literals = ZkBinary::parse_literals(literals_section)?;
         let literals = ZkBinary::parse_literals(literals_section)?;
         let witnesses = ZkBinary::parse_contract(contract_section)?;
         let witnesses = ZkBinary::parse_contract(contract_section)?;
         let opcodes = ZkBinary::parse_circuit(circuit_section)?;
         let opcodes = ZkBinary::parse_circuit(circuit_section)?;
+
         // TODO: Debug info
         // TODO: Debug info
 
 
-        Ok(Self { constants, literals, witnesses, opcodes })
+        Ok(Self { namespace, constants, literals, witnesses, opcodes })
     }
     }
 
 
     fn parse_constants(bytes: &[u8]) -> Result<Vec<(VarType, String)>> {
     fn parse_constants(bytes: &[u8]) -> Result<Vec<(VarType, String)>> {

+ 12 - 2
src/zkas/parser.rs

@@ -14,6 +14,9 @@ use super::{
 /// These can not be used anywhere except where they are expected.
 /// These can not be used anywhere except where they are expected.
 const KEYWORDS: [&str; 3] = ["constant", "contract", "circuit"];
 const KEYWORDS: [&str; 3] = ["constant", "contract", "circuit"];
 
 
+/// Forbidden namespaces
+const NOPE_NS: [&str; 4] = [".constant", ".literal", ".contract", ".circuit"];
+
 /// Valid EcFixedPoint constant names supported by the VM.
 /// Valid EcFixedPoint constant names supported by the VM.
 const VALID_ECFIXEDPOINT: [&str; 1] = ["VALUE_COMMIT_RANDOM"];
 const VALID_ECFIXEDPOINT: [&str; 1] = ["VALUE_COMMIT_RANDOM"];
 
 
@@ -38,7 +41,7 @@ impl Parser {
         Self { tokens, error }
         Self { tokens, error }
     }
     }
 
 
-    pub fn parse(&self) -> (Vec<Constant>, Vec<Witness>, Vec<Statement>) {
+    pub fn parse(&self) -> (String, Vec<Constant>, Vec<Witness>, Vec<Statement>) {
         // We use these to keep state while parsing.
         // We use these to keep state while parsing.
         let mut namespace = None;
         let mut namespace = None;
         let (mut declaring_constant, mut declared_constant) = (false, false);
         let (mut declaring_constant, mut declared_constant) = (false, false);
@@ -133,6 +136,13 @@ impl Parser {
                             );
                             );
                         }
                         }
                     } else {
                     } else {
+                        if NOPE_NS.contains(&$t[0].token.as_str()) {
+                            self.error.abort(
+                                &format!("'{}' cannot be a namespace.", $t[0].token),
+                                $t[0].line,
+                                $t[0].column,
+                            );
+                        }
                         namespace = Some($t[0].token.clone());
                         namespace = Some($t[0].token.clone());
                     }
                     }
                 };
                 };
@@ -273,7 +283,7 @@ impl Parser {
             self.error.abort("Circuit section is empty.", 0, 0);
             self.error.abort("Circuit section is empty.", 0, 0);
         }
         }
 
 
-        (constants, witnesses, statements)
+        (ns, constants, witnesses, statements)
     }
     }
 
 
     fn check_section_structure(&self, section: &str, tokens: Vec<Token>) {
     fn check_section_structure(&self, section: &str, tokens: Vec<Token>) {