circom-bshield/circuits/account_change.circom

107 lines
2.7 KiB
Plaintext
Raw Normal View History

2022-10-31 14:08:28 +07:00
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);