working account_change.circom
This commit is contained in:
106
circuits/account_change.circom
Normal file
106
circuits/account_change.circom
Normal file
@ -0,0 +1,106 @@
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../circomlib/circuits/smt/smtprocessor.circom";
|
||||
include "../circomlib/circuits/smt/smtverifier.circom";
|
||||
include "../circomlib/circuits/comparators.circom";
|
||||
|
||||
|
||||
// input:
|
||||
// oldRoot
|
||||
// from
|
||||
// amount
|
||||
// to
|
||||
// signature
|
||||
// extra input:
|
||||
// fromBalance
|
||||
// toBalance
|
||||
// fromSiblings
|
||||
// toSiblings
|
||||
// output:
|
||||
// newRoot
|
||||
//
|
||||
// proves:
|
||||
// signature is verified
|
||||
// from balance >= amount
|
||||
// oldRoot calculated
|
||||
//
|
||||
// limited by sparse merkle tree implementation,
|
||||
// we can't directly change the tree at once
|
||||
// we can only update the tree with each leaf changes
|
||||
// so we have an intermediate root showing from balance is reduced
|
||||
//
|
||||
// for each merkle tree proof, a list of siblings is required
|
||||
// and provided as inputs
|
||||
//
|
||||
// original balance must be provided to calculate the new balance
|
||||
//
|
||||
// assumptions:
|
||||
// - from and to is in tree
|
||||
template AccountChange(nlevels) {
|
||||
signal input from;
|
||||
signal input amount;
|
||||
signal input to;
|
||||
|
||||
signal input oldRoot;
|
||||
|
||||
signal input signature;
|
||||
|
||||
signal input fromBalance;
|
||||
signal input fromSiblings[nlevels];
|
||||
signal input toBalance;
|
||||
signal input toSiblings[nlevels];
|
||||
|
||||
signal output newRoot;
|
||||
|
||||
// verify signature
|
||||
|
||||
// verify user's balance
|
||||
component BalanceCheck = SMTVerifier(nlevels);
|
||||
BalanceCheck.enabled <== 1;
|
||||
BalanceCheck.root <== oldRoot;
|
||||
for (var i = 0; i < nlevels; i++)
|
||||
BalanceCheck.siblings[i] <== fromSiblings[i];
|
||||
BalanceCheck.oldKey <== from;
|
||||
BalanceCheck.oldValue <== fromBalance;
|
||||
BalanceCheck.isOld0 <== 0;
|
||||
BalanceCheck.key <== from;
|
||||
BalanceCheck.value <== fromBalance;
|
||||
BalanceCheck.fnc <== 0;
|
||||
|
||||
// abort if balance is not enough
|
||||
component EnoughMoney = GreaterThan(252);
|
||||
EnoughMoney.in[0] <== fromBalance;
|
||||
EnoughMoney.in[1] <== amount;
|
||||
EnoughMoney.out === 1;
|
||||
|
||||
// update from's balance
|
||||
component ReduceFrom = SMTProcessor(nlevels);
|
||||
ReduceFrom.oldRoot <== oldRoot;
|
||||
for (var i = 0; i < nlevels; i++)
|
||||
ReduceFrom.siblings[i] <== fromSiblings[i];
|
||||
ReduceFrom.oldKey <== from;
|
||||
ReduceFrom.oldValue <== fromBalance;
|
||||
ReduceFrom.isOld0 <== 0;
|
||||
ReduceFrom.newKey <== from;
|
||||
ReduceFrom.newValue <== fromBalance - amount;
|
||||
ReduceFrom.fnc[0] <== 0;
|
||||
ReduceFrom.fnc[1] <== 1;
|
||||
|
||||
// update to's balance
|
||||
component IncreaseTo = SMTProcessor(nlevels);
|
||||
IncreaseTo.oldRoot <== ReduceFrom.newRoot;
|
||||
for (var i = 0; i < nlevels; i++)
|
||||
IncreaseTo.siblings[i] <== toSiblings[i];
|
||||
IncreaseTo.oldKey <== to;
|
||||
IncreaseTo.oldValue <== toBalance;
|
||||
IncreaseTo.isOld0 <== 0;
|
||||
IncreaseTo.newKey <== to;
|
||||
IncreaseTo.newValue <== toBalance + amount;
|
||||
IncreaseTo.fnc[0] <== 0;
|
||||
IncreaseTo.fnc[1] <== 1;
|
||||
|
||||
// output the new root
|
||||
newRoot <== IncreaseTo.newRoot;
|
||||
}
|
||||
|
||||
component main {public [oldRoot]} = AccountChange(10);
|
Reference in New Issue
Block a user