Parcourir la source

add new psuedocode contract script file

narodnik il y a 5 ans
Parent
commit
8d17c4785c
4 fichiers modifiés avec 187 ajouts et 41 suppressions
  1. 120 0
      proofs/sapling.pseudocode
  2. 31 32
      proofs/sapling3.prf
  3. 35 8
      scripts/parser.py
  4. 1 1
      scripts/sapvi.vim

+ 120 - 0
proofs/sapling.pseudocode

@@ -0,0 +1,120 @@
+# :set syntax=sapvi
+# :source ../scripts/sapvi.vim
+const:
+    G_VCV: SubgroupPoint
+    G_VCR: SubgroupPoint
+    G_SPEND: SubgroupPoint
+    G_PROOF: SubgroupPoint
+    G_NOTE_COMMIT_R: SubgroupPoint
+    G_NULL: SubgroupPoint
+
+    CRH_IVK: Blake2sPersonalization
+    NOTE_COMMIT: PedersenPersonalization
+    MERKLE: list<PedersenPersonalization>
+    PRF_NF: Blake2sPersonalization
+
+contract input_spend(
+    value: BinaryNumber
+    randomness: BinaryNumber
+    ak: Point
+    ar: BinaryNumber
+    nsk: BinaryNumber
+    g_d: Point
+    commitment_randomness: BinaryNumber
+    auth_path: [(Scalar, Bool)]
+    anchor: Scalar
+) -> (Point, Point, Scalar, BinaryNumber):
+    let rk: Point = ak + ar * G_SPEND
+    emit rk
+
+    let nk: Point = nsk * G_PROOF
+
+    let mut ivk_preimage: BinaryNumber = []
+    ivk_preimage.put(ak)
+
+    let mut nf_preimage: BinaryNumber = []
+
+    ivk_preimage.put(nk)
+    nf_preimage.put(nk)
+
+    assert ivk_preimage.len() == 512
+    assert nf_preimage.len() == 256
+
+    let mut ivk = blake2s(ivk_preimage, CRH_IVK)
+    ivk.truncate(Fr.CAPACITY)
+    # This will error if ivk.len() != 256
+    #let ivk: Fr = ivk as Fr
+    let pk_d: Point = ivk * g_d
+
+    let cv: Point = value * G_VCV + rcv * G_VCR
+    emit cv
+
+    let mut note_contents: BinaryNumber = []
+    note_contents.put(value)
+    note_contents.put(g_d)
+    note_contents.put(p_k)
+    assert note_contents.len() == 64 + 256 + 256
+
+    let mut cm = pedersen_hash(note_contents, NOTE_COMMIT)
+    cm += commitment_randomness * G_NOTE_COMMIT_R
+
+    let mut position = []
+    let mut cur: Scalar = cm.u
+
+    for i in range(auth_path.size()):
+        let (node: Scalar, is_right: Bool) = auth_path[i]
+
+        position.push(is_right)
+
+        # Scalar -> AllocatedNum
+        let (left: Scalar, right: Scalar) = swap_if(is_right, cur, node)
+
+        let mut preimage: BinaryNumber = []
+        preimage.put(left)
+        preimage.put(right)
+
+        cur = pedersen_hash(MERKLE_TREE[i], preimage).u
+
+    enforce cur == rt
+    emit rt
+
+    let rho: Point = rho + position * G_NULL
+
+    nf_preimage.put(rho)
+    assert nf_preimage.len() == 512
+
+    let nf: BinaryNumber = blake2s(nf_preimage, PRF_NF)
+    emit nf
+
+contract output_mint(
+    value: BinaryNumber,
+    randomness: BinaryNumber,
+    g_d: Point,
+    esk: BinaryNumber,
+    pk_d: Point,
+    commitment_randomness: Scalar
+) -> (Point, Point, Scalar):
+    let cv: Point = value * G_VCV + rcv * G_VCR
+    emit cv
+
+    let mut note_contents: Binary = []
+    note_contents.put(value)
+
+    let epk: Point = esk * g_d
+    emit epk
+
+    let v_contents: Scalar = pk_d.v
+    let sign_bit: Bool = pk_d.u.is_odd()
+
+    note_contents.put(v_contents)
+    note_contents.put(sign_bit)
+
+    assert len(note_contents) == 64 + 256 + 256
+
+    let mut cm: Point = pedersen_hash(note_contents, NOTE_COMMIT)
+    let rcm: Point = commitment_randomness * G_NOTE_COMMIT_R
+    cm += rcm
+
+    let cmu: Scalar = cm.u
+    emit cmu
+

+ 31 - 32
proofs/sapling3.prf

@@ -7,12 +7,12 @@
 # Difference between AllocatedNum and Num
 # Difference between AllocatedNum and Num
 # Why BlsScalar vs JJScalar?
 # Why BlsScalar vs JJScalar?
 const:
 const:
-    G_VCV: Point
-    G_VCR: Point
-    G_SPEND: Point
-    G_PROOF: Point
-    G_NOTE_COMMIT_R: Point
-    G_NULL: Point
+    G_VCV: SubgroupPoint
+    G_VCR: SubgroupPoint
+    G_SPEND: SubgroupPoint
+    G_PROOF: SubgroupPoint
+    G_NOTE_COMMIT_R: SubgroupPoint
+    G_NULL: SubgroupPoint
 
 
     CRH_IVK: Blake2sPersonalization
     CRH_IVK: Blake2sPersonalization
     NOTE_COMMIT: PedersenPersonalization
     NOTE_COMMIT: PedersenPersonalization
@@ -21,12 +21,12 @@ const:
 
 
 def value_commit(value: U64, randomness: Scalar) -> Binary:
 def value_commit(value: U64, randomness: Scalar) -> Binary:
     let value_bits: Binary = value as Binary
     let value_bits: Binary = value as Binary
-    let value: Point = value * G_VCV
+    let value: SubgroupPoint = value * G_VCV
 
 
     let rcv: Binary = randomness as Binary
     let rcv: Binary = randomness as Binary
-    let rcv: Point = rcv * G_VCR
+    let rcv: SubgroupPoint = rcv * G_VCR
 
 
-    let cv: Point = value + rcv
+    let cv: SubgroupPoint = value + rcv
     emit cv
     emit cv
     return value_bits
     return value_bits
 
 
@@ -36,29 +36,29 @@ contract input_burn(
     value: U64,                 # ValueCommitment.value
     value: U64,                 # ValueCommitment.value
     randomness: Scalar,         # ValueCommitment.randomness
     randomness: Scalar,         # ValueCommitment.randomness
 
 
-    ak: Point,                  # from ProofGenerationKey
+    ak: SubgroupPoint,                  # from ProofGenerationKey
     ar: Scalar,
     ar: Scalar,
 
 
     nsk: Scalar,                # from ProofGenerationKey
     nsk: Scalar,                # from ProofGenerationKey
 
 
-    g_d: Point,                 # Computed from payment_address
+    g_d: SubgroupPoint,                 # Computed from payment_address
 
 
     commitment_randomness: Scalar,
     commitment_randomness: Scalar,
 
 
     auth_path: list<(Scalar, Bool)>,
     auth_path: list<(Scalar, Bool)>,
 
 
     anchor: Scalar
     anchor: Scalar
-) -> (Point, Point, Point, Binary):
+) -> (SubgroupPoint, SubgroupPoint, SubgroupPoint, Binary):
     let ak = witness(ak)
     let ak = witness(ak)
     ak.assert_not_small_order()
     ak.assert_not_small_order()
 
 
     let ar: Binary = ar as Binary
     let ar: Binary = ar as Binary
-    let ar: Point = ar * G_SPEND
+    let ar: SubgroupPoint = ar * G_SPEND
 
 
-    let rk: Point = ak + ar
+    let rk: SubgroupPoint = ak + ar
 
 
     let nsk: Binary = nsk as Binary
     let nsk: Binary = nsk as Binary
-    let nk: Point = nsk * G_PROOF
+    let nk: SubgroupPoint = nsk * G_PROOF
 
 
     let mut ivk_preimage: Binary = []
     let mut ivk_preimage: Binary = []
     # Must be Binary as well
     # Must be Binary as well
@@ -75,14 +75,14 @@ contract input_burn(
     let mut ivk: Binary = blake2s(ivk_preimage, CRH_IVK)
     let mut ivk: Binary = blake2s(ivk_preimage, CRH_IVK)
     ivk.truncate(Scalar.CAPACITY)
     ivk.truncate(Scalar.CAPACITY)
 
 
-    let g_d: Point = witness g_d
+    let g_d: SubgroupPoint = witness g_d
     g_d.assert_not_small_order()
     g_d.assert_not_small_order()
 
 
-    let pk_d: Point = ivk * g_d
+    let pk_d: SubgroupPoint = ivk * g_d
 
 
     let mut note_contents: Binary = []
     let mut note_contents: Binary = []
 
 
-    let (cv: Point, value_bits: Binary) = value_commit(value, randomness)
+    let (cv: SubgroupPoint, value_bits: Binary) = value_commit(value, randomness)
 
 
     let mut value_num: Num = Num.zero()
     let mut value_num: Num = Num.zero()
     let mut coeff: Scalar = Scalar.one()
     let mut coeff: Scalar = Scalar.one()
@@ -98,15 +98,14 @@ contract input_burn(
 
 
     assert len(note_contents) == 64 + 256 + 256
     assert len(note_contents) == 64 + 256 + 256
 
 
-    let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
+    let mut cm: SubgroupPoint = pedersen_hash(NOTE_COMMIT, note_contents)
     let rcm: Binary = commitment_randomness as Binary
     let rcm: Binary = commitment_randomness as Binary
-    let rcm: Point = rcm * G_NOTE_COMMIT_R
+    let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
     cm += rcm
     cm += rcm
 
 
     let mut position_bits: Binary = []
     let mut position_bits: Binary = []
     let mut cur: Scalar = cm.u
     let mut cur: Scalar = cm.u
 
 
-    # This should be fixed: for i in 0..N then use array indexing
     for i in range(auth_path.size()):
     for i in range(auth_path.size()):
         let (node: Scalar, is_right: Bool) = auth_path[i]
         let (node: Scalar, is_right: Bool) = auth_path[i]
 
 
@@ -122,12 +121,12 @@ contract input_burn(
 
 
         cur = pedersen_hash(MERKLE_TREE[i], preimage).u
         cur = pedersen_hash(MERKLE_TREE[i], preimage).u
 
 
-    let rt: Point = EncryptedNum.from(anchor)
+    let rt: SubgroupPoint = EncryptedNum.from(anchor)
 
 
     enforce (cur - rt) * value_num == 0
     enforce (cur - rt) * value_num == 0
 
 
-    let position: Point = position_bits * G_NULL
-    let rho: Point = cm + position
+    let position: SubgroupPoint = position_bits * G_NULL
+    let rho: SubgroupPoint = cm + position
 
 
     nf_preimage.extend(rho)
     nf_preimage.extend(rho)
     assert len(nf_preimage) == 512
     assert len(nf_preimage) == 512
@@ -139,23 +138,23 @@ contract output_mint(
     value: U64,
     value: U64,
     randomness: Scalar,
     randomness: Scalar,
 
 
-    g_d: Point,
+    g_d: SubgroupPoint,
 
 
     esk: Scalar,
     esk: Scalar,
-    pk_d: Point,
+    pk_d: SubgroupPoint,
 
 
     commitment_randomness: Scalar
     commitment_randomness: Scalar
-) -> (Point, Point, Scalar):
+) -> (SubgroupPoint, SubgroupPoint, Scalar):
     let value_bits: Binary = value_commit(value, randomness)
     let value_bits: Binary = value_commit(value, randomness)
 
 
     let mut note_contents: Binary = []
     let mut note_contents: Binary = []
     note_contents.extend(value_bits)
     note_contents.extend(value_bits)
 
 
-    let g_d: Point = witness g_d
-    assert is_not_small_order(g_d)
+    let g_d: EdwardsPoint = witness(g_d)
+    g_d.assert_not_small_order()
 
 
     let esk: Binary = esk as Binary
     let esk: Binary = esk as Binary
-    let epk: Point = esk * g_d
+    let epk: SubgroupPoint = esk * g_d
 
 
     let v_contents: Binary = pk_d.v as Binary
     let v_contents: Binary = pk_d.v as Binary
 
 
@@ -166,10 +165,10 @@ contract output_mint(
 
 
     assert len(note_contents) == 64 + 256 + 256
     assert len(note_contents) == 64 + 256 + 256
 
 
-    let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
+    let mut cm: SubgroupPoint = pedersen_hash(NOTE_COMMIT, note_contents)
 
 
     let rcm: Binary = commitment_randomness as Binary
     let rcm: Binary = commitment_randomness as Binary
-    let rcm: Point = rcm * G_NOTE_COMMIT_R
+    let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
 
 
     cm += rcm
     cm += rcm
 
 

+ 35 - 8
scripts/parser.py

@@ -554,6 +554,8 @@ class ContractCodeLineTransformer(lark.Transformer):
         return ("return", obj)
         return ("return", obj)
     def emit_statement(self, obj):
     def emit_statement(self, obj):
         return ("emit", obj)
         return ("emit", obj)
+    def method_statement(self, obj):
+        return ("method", obj)
 
 
     def point(self, _):
     def point(self, _):
         return "Point"
         return "Point"
@@ -582,6 +584,7 @@ def interpret_contract_line(text, stack, consts):
         statement: let_statement
         statement: let_statement
                  | return_statement
                  | return_statement
                  | emit_statement
                  | emit_statement
+                 | method_statement
 
 
         let_statement: "let" variable_assign "=" expr
         let_statement: "let" variable_assign "=" expr
         mutable: "mut"
         mutable: "mut"
@@ -594,11 +597,13 @@ def interpret_contract_line(text, stack, consts):
             | mul_expr
             | mul_expr
             | add_expr
             | add_expr
             | funccall_expr
             | funccall_expr
+            | empty_list_expr
 
 
         as_expr: variable_name "as" type
         as_expr: variable_name "as" type
         mul_expr: variable_name "*" variable_name
         mul_expr: variable_name "*" variable_name
         add_expr: variable_name "+" variable_name
         add_expr: variable_name "+" variable_name
         funccall_expr: function_name "(" [variable_name ("," variable_name)*] ")"
         funccall_expr: function_name "(" [variable_name ("," variable_name)*] ")"
+        empty_list_expr: "[]"
 
 
         return_statement: "return" variable_name
         return_statement: "return" variable_name
                         | "return" variable_tuple
                         | "return" variable_tuple
@@ -606,6 +611,8 @@ def interpret_contract_line(text, stack, consts):
 
 
         emit_statement: "emit" variable_name
         emit_statement: "emit" variable_name
 
 
+        method_statement: variable_name "." funccall_expr
+
         variable_name: NAME
         variable_name: NAME
         function_name: NAME
         function_name: NAME
         type: u64 | scalar | point | binary
         type: u64 | scalar | point | binary
@@ -654,7 +661,7 @@ def create_contract_header(contract_def):
     return header
     return header
 
 
 # Worst code ever
 # Worst code ever
-def compile_let2(line, stack, consts, funcs, statement):
+def compile_let2(line, stack, consts, funcs, selfvars, statement):
     lhs = []
     lhs = []
     for variable_decl in statement[0]:
     for variable_decl in statement[0]:
         assert len(variable_decl) == 2 or \
         assert len(variable_decl) == 2 or \
@@ -696,7 +703,9 @@ def compile_let2(line, stack, consts, funcs, statement):
     expr_type = expr.data
     expr_type = expr.data
     expr = expr.children
     expr = expr.children
     if expr_type == "funccall_expr":
     if expr_type == "funccall_expr":
-        ceval = funccall_expr(line, stack, consts, funcs, expr, code)
+        ceval = funccall_expr(line, stack, consts, funcs, selfvars, expr, code)
+    elif expr_type == "empty_list_expr":
+        ceval = code + "vec![];", ["Binary"]
     #code = "let " + ("mut " if is_mutable else "") + variable_name + " = "
     #code = "let " + ("mut " if is_mutable else "") + variable_name + " = "
 
 
     if ceval is None:
     if ceval is None:
@@ -715,7 +724,7 @@ def compile_let2(line, stack, consts, funcs, statement):
             
             
     return code
     return code
 
 
-def funccall_expr(line, stack, consts, funcs, expr, code):
+def funccall_expr(line, stack, consts, funcs, selfvars, expr, code):
     func_name, arguments = expr[0], expr[1:]
     func_name, arguments = expr[0], expr[1:]
 
 
     if func_name not in funcs:
     if func_name not in funcs:
@@ -724,7 +733,8 @@ def funccall_expr(line, stack, consts, funcs, expr, code):
         print("line:", line.text, "line:", line.lineno)
         print("line:", line.text, "line:", line.lineno)
         return None
         return None
 
 
-    arguments = ["self." + arg for arg in arguments]
+    arguments = [("self." + arg if arg in selfvars else arg)
+                 for arg in arguments]
 
 
     code += "%s(cs.namespace(|| \"%s\"), %s)?;" % (
     code += "%s(cs.namespace(|| \"%s\"), %s)?;" % (
         func_name, line.text, ", ".join(arguments))
         func_name, line.text, ", ".join(arguments))
@@ -732,20 +742,37 @@ def funccall_expr(line, stack, consts, funcs, expr, code):
     return_type = funcs[func_name][-1][-1]
     return_type = funcs[func_name][-1][-1]
     return code, return_type
     return code, return_type
 
 
+def compile_method_call(line, stack, consts, funcs, selfvars, statement):
+    variable = statement[0]
+    method = statement[1].children[0]
+    arguments = statement[1].children[1:]
+
+    arguments = [("self." + arg if arg in selfvars else arg)
+                 for arg in arguments]
+
+    return "%s.%s(%s);" % (variable, method, ", ".join(arguments))
+
 def interpret_contract(contract, consts, funcs):
 def interpret_contract(contract, consts, funcs):
     contract_def = parse_contract_def(contract[0].text)
     contract_def = parse_contract_def(contract[0].text)
     contract_code = create_contract_header(contract_def)
     contract_code = create_contract_header(contract_def)
 
 
+    selfvars = set(varname[0] for varname in contract_def[1])
     stack = dict(contract_def[1])
     stack = dict(contract_def[1])
-    for line in contract[1:2]:
+    for line in contract[1:10]:
         indent = " " * 4 * int(line.level + 1)
         indent = " " * 4 * int(line.level + 1)
         statement_type, statement = interpret_contract_line(line.text, stack, consts)
         statement_type, statement = interpret_contract_line(line.text, stack, consts)
         #pprint.pprint(statement_type)
         #pprint.pprint(statement_type)
         if statement_type == "let":
         if statement_type == "let":
-            code = compile_let2(line, stack, consts, funcs, statement)
+            code = compile_let2(line, stack, consts, funcs, selfvars, statement)
             if code is None:
             if code is None:
                 return
                 return
-            contract_code += indent + code + "\n"
+        elif statement_type == "method":
+            code = compile_method_call(line, stack, consts, funcs,
+                                       selfvars, statement)
+            if code is None:
+                return
+
+        contract_code += indent + code + "\n"
 
 
     contract_code += " " * 8 + "Ok(())\n"
     contract_code += " " * 8 + "Ok(())\n"
     contract_code += " " * 4 + "}\n"
     contract_code += " " * 4 + "}\n"
@@ -801,7 +828,7 @@ def main(argv):
     for _, contract in contracts.items():
     for _, contract in contracts.items():
         output += contract[0]
         output += contract[0]
 
 
-    print(output)
+    #print(output)
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     main(sys.argv)
     main(sys.argv)

+ 1 - 1
scripts/sapvi.vim

@@ -4,7 +4,7 @@ endif
 
 
 syn keyword sapviKeyword assert enforce for in def return const as let emit contract private proof
 syn keyword sapviKeyword assert enforce for in def return const as let emit contract private proof
 syn keyword sapviAttr mut
 syn keyword sapviAttr mut
-syn keyword sapviType Point Scalar EncryptedNum list Bool U64 Num Binary
+syn keyword sapviType BinaryNumber Point Fr SubgroupPoint EdwardsPoint Scalar EncryptedNum list Bool U64 Num Binary
 syn match sapviFunction "\zs[a-zA-Z0-9_]*\ze("
 syn match sapviFunction "\zs[a-zA-Z0-9_]*\ze("
 syn match sapviComment "#.*$"
 syn match sapviComment "#.*$"
 syn match sapviNumber '\d\+'
 syn match sapviNumber '\d\+'