瀏覽代碼

add missing code for inputs

narodnik 4 年之前
父節點
當前提交
70293fd181
共有 2 個文件被更改,包括 112 次插入4 次删除
  1. 110 4
      bin/daod/demo/main.py
  2. 2 0
      src/tx/builder.rs

+ 110 - 4
bin/daod/demo/main.py

@@ -20,7 +20,11 @@ class TransactionBuilder:
         clear_input.signature_secret = signature_secret
         self.clear_inputs.append(clear_input)
 
-    def add_input(self, input):
+    def add_input(self, all_coins, secret, note):
+        input = ClassNamespace()
+        input.all_coins = all_coins
+        input.secret = secret
+        input.note = note
         self.inputs.append(input)
 
     def add_output(self, value, token_id, public):
@@ -54,8 +58,21 @@ class TransactionBuilder:
             tx.clear_inputs.append(tx_clear_input)
 
         input_blinds = []
+        signature_secrets = []
         for input in self.inputs:
+            # FIXME: BUG - see corresponding builder.rs file
+            input_blinds.append(input.note.value_blind)
+
+            signature_secret = self.ec.random_scalar()
+            signature_secrets.append(signature_secret)
+
             tx_input = ClassNamespace()
+            tx_input.__name__ = "TransactionInput"
+            tx_input.burn_proof = BurnProof(
+                input.note.value, input.note.token_id, input.note.value_blind,
+                token_blind, input.note.serial, input.note.coin_blind,
+                input.secret, input.all_coins, signature_secret, self.ec)
+            tx_input.revealed = tx_input.burn_proof.get_revealed()
             tx.inputs.append(tx_input)
 
         assert self.outputs
@@ -97,13 +114,71 @@ class TransactionBuilder:
             secret = info.signature_secret
             signature = sign(unsigned_tx_data, secret, self.ec)
             input.signature = signature
-        for (input, info) in zip(tx.inputs, self.inputs):
-            secret = info.signature_secret
-            signature = sign(unsigned_tx_data, secret, self.ec)
+        for (input, signature_secret) in zip(tx.inputs, signature_secrets):
+            signature = sign(unsigned_tx_data, signature_secret, self.ec)
             input.signature = signature
 
         return tx
 
+class BurnProof:
+
+    def __init__(self, value, token_id, value_blind, token_blind, serial,
+                 coin_blind, secret, all_coins, signature_secret, ec):
+        self.value = value
+        self.token_id = token_id
+        self.value_blind = value_blind
+        self.token_blind = token_blind
+        self.serial = serial
+        self.coin_blind = coin_blind
+        self.secret = secret
+        self.all_coins = all_coins
+        self.signature_secret = signature_secret
+
+        self.ec = ec
+
+    def get_revealed(self):
+        revealed = ClassNamespace()
+        revealed.nullifier = ff_hash(self.secret, self.serial)
+
+        revealed.value_commit = pedersen_encrypt(
+            self.value, self.value_blind, self.ec
+        )
+        revealed.token_commit = pedersen_encrypt(
+            self.token_id, self.token_blind, self.ec
+        )
+
+        revealed.all_coins = self.all_coins
+
+        revealed.signature_public = self.ec.multiply(self.signature_secret,
+                                                     self.ec.G)
+
+        return revealed
+
+    def verify(self, public):
+        revealed = self.get_revealed()
+
+        public_key = self.ec.multiply(self.secret, self.ec.G)
+        coin = ff_hash(
+            self.ec.p,
+            public_key[0],
+            public_key[1],
+            self.value,
+            self.token_id,
+            self.serial,
+            self.coin_blind
+        )
+        # Merkle root check
+        if coin not in self.all_coins:
+            return False
+
+        return all([
+            revealed.nullifier == public.nullifier,
+            revealed.value_commit == public.value_commit,
+            revealed.token_commit == public.token_commit,
+            revealed.all_coins == public.all_coins,
+            revealed.signature_public == public.signature_public
+        ])
+
 class MintProof:
 
     def __init__(self, value, token_id, value_blind, token_blind, serial,
@@ -289,6 +364,37 @@ def main(argv):
         print(f"tx verify failed: {reason}", file=sys.stderr)
         return -1
 
+    assert len(tx.outputs) > 0
+    note = tx.outputs[0].enc_note
+    coin = ff_hash(
+        ec.p,
+        public[0],
+        public[1],
+        note.value,
+        note.token_id,
+        note.serial,
+        note.coin_blind
+    )
+    assert coin == tx.outputs[0].mint_proof.get_revealed().coin
+    all_coins = [coin]
+
+    builder = TransactionBuilder(ec)
+    builder.add_input(all_coins, secret, note)
+
+    secret2 = ec.random_scalar()
+    public2 = ec.multiply(secret, ec.G)
+
+    builder.add_output(1000, token_id, public2)
+    # Change
+    builder.add_output(note.value - 1000, token_id, public)
+
+    tx = builder.build()
+
+    is_verify, reason = tx.verify()
+    if not is_verify:
+        print(f"tx2 verify failed: {reason}", file=sys.stderr)
+        return -1
+
     return 0
 
 if __name__ == "__main__":

+ 2 - 0
src/tx/builder.rs

@@ -89,6 +89,8 @@ impl TransactionBuilder {
         let mut input_blinds = vec![];
         let mut signature_secrets = vec![];
         for input in self.inputs {
+            // FIXME: BUG - looks like we are reusing the value_blind from the output
+            // This must be a completely new random value or the value_commit will be the same.
             input_blinds.push(input.note.value_blind);
 
             let signature_secret = SecretKey::random(&mut OsRng);