Przeglądaj źródła

add new psuedocode contract script file

narodnik 5 lat temu
rodzic
commit
8d17c4785c
4 zmienionych plików z 187 dodań i 41 usunięć
  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
 # Why BlsScalar vs JJScalar?
 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
     NOTE_COMMIT: PedersenPersonalization
@@ -21,12 +21,12 @@ const:
 
 def value_commit(value: U64, randomness: Scalar) -> 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: Point = rcv * G_VCR
+    let rcv: SubgroupPoint = rcv * G_VCR
 
-    let cv: Point = value + rcv
+    let cv: SubgroupPoint = value + rcv
     emit cv
     return value_bits
 
@@ -36,29 +36,29 @@ contract input_burn(
     value: U64,                 # ValueCommitment.value
     randomness: Scalar,         # ValueCommitment.randomness
 
-    ak: Point,                  # from ProofGenerationKey
+    ak: SubgroupPoint,                  # from ProofGenerationKey
     ar: Scalar,
 
     nsk: Scalar,                # from ProofGenerationKey
 
-    g_d: Point,                 # Computed from payment_address
+    g_d: SubgroupPoint,                 # Computed from payment_address
 
     commitment_randomness: Scalar,
 
     auth_path: list<(Scalar, Bool)>,
 
     anchor: Scalar
-) -> (Point, Point, Point, Binary):
+) -> (SubgroupPoint, SubgroupPoint, SubgroupPoint, Binary):
     let ak = witness(ak)
     ak.assert_not_small_order()
 
     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 nk: Point = nsk * G_PROOF
+    let nk: SubgroupPoint = nsk * G_PROOF
 
     let mut ivk_preimage: Binary = []
     # Must be Binary as well
@@ -75,14 +75,14 @@ contract input_burn(
     let mut ivk: Binary = blake2s(ivk_preimage, CRH_IVK)
     ivk.truncate(Scalar.CAPACITY)
 
-    let g_d: Point = witness g_d
+    let g_d: SubgroupPoint = witness g_d
     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 (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 coeff: Scalar = Scalar.one()
@@ -98,15 +98,14 @@ contract input_burn(
 
     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: Point = rcm * G_NOTE_COMMIT_R
+    let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
     cm += rcm
 
     let mut position_bits: Binary = []
     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()):
         let (node: Scalar, is_right: Bool) = auth_path[i]
 
@@ -122,12 +121,12 @@ contract input_burn(
 
         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
 
-    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)
     assert len(nf_preimage) == 512
@@ -139,23 +138,23 @@ contract output_mint(
     value: U64,
     randomness: Scalar,
 
-    g_d: Point,
+    g_d: SubgroupPoint,
 
     esk: Scalar,
-    pk_d: Point,
+    pk_d: SubgroupPoint,
 
     commitment_randomness: Scalar
-) -> (Point, Point, Scalar):
+) -> (SubgroupPoint, SubgroupPoint, Scalar):
     let value_bits: Binary = value_commit(value, randomness)
 
     let mut note_contents: Binary = []
     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 epk: Point = esk * g_d
+    let epk: SubgroupPoint = esk * g_d
 
     let v_contents: Binary = pk_d.v as Binary
 
@@ -166,10 +165,10 @@ contract output_mint(
 
     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: Point = rcm * G_NOTE_COMMIT_R
+    let rcm: SubgroupPoint = rcm * G_NOTE_COMMIT_R
 
     cm += rcm
 

+ 35 - 8
scripts/parser.py

@@ -554,6 +554,8 @@ class ContractCodeLineTransformer(lark.Transformer):
         return ("return", obj)
     def emit_statement(self, obj):
         return ("emit", obj)
+    def method_statement(self, obj):
+        return ("method", obj)
 
     def point(self, _):
         return "Point"
@@ -582,6 +584,7 @@ def interpret_contract_line(text, stack, consts):
         statement: let_statement
                  | return_statement
                  | emit_statement
+                 | method_statement
 
         let_statement: "let" variable_assign "=" expr
         mutable: "mut"
@@ -594,11 +597,13 @@ def interpret_contract_line(text, stack, consts):
             | mul_expr
             | add_expr
             | funccall_expr
+            | empty_list_expr
 
         as_expr: variable_name "as" type
         mul_expr: variable_name "*" variable_name
         add_expr: variable_name "+" variable_name
         funccall_expr: function_name "(" [variable_name ("," variable_name)*] ")"
+        empty_list_expr: "[]"
 
         return_statement: "return" variable_name
                         | "return" variable_tuple
@@ -606,6 +611,8 @@ def interpret_contract_line(text, stack, consts):
 
         emit_statement: "emit" variable_name
 
+        method_statement: variable_name "." funccall_expr
+
         variable_name: NAME
         function_name: NAME
         type: u64 | scalar | point | binary
@@ -654,7 +661,7 @@ def create_contract_header(contract_def):
     return header
 
 # Worst code ever
-def compile_let2(line, stack, consts, funcs, statement):
+def compile_let2(line, stack, consts, funcs, selfvars, statement):
     lhs = []
     for variable_decl in statement[0]:
         assert len(variable_decl) == 2 or \
@@ -696,7 +703,9 @@ def compile_let2(line, stack, consts, funcs, statement):
     expr_type = expr.data
     expr = expr.children
     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 + " = "
 
     if ceval is None:
@@ -715,7 +724,7 @@ def compile_let2(line, stack, consts, funcs, statement):
             
     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:]
 
     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)
         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)?;" % (
         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 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):
     contract_def = parse_contract_def(contract[0].text)
     contract_code = create_contract_header(contract_def)
 
+    selfvars = set(varname[0] for varname in 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)
         statement_type, statement = interpret_contract_line(line.text, stack, consts)
         #pprint.pprint(statement_type)
         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:
                 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 += " " * 4 + "}\n"
@@ -801,7 +828,7 @@ def main(argv):
     for _, contract in contracts.items():
         output += contract[0]
 
-    print(output)
+    #print(output)
 
 if __name__ == "__main__":
     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 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 sapviComment "#.*$"
 syn match sapviNumber '\d\+'