Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/erc20 integration #29

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ get dependencies `git submodule update --init --recursive`
Finally you will need to download the ~400MB proving key from [here](https://github.com/barryWhiteHat/miximus/releases/download/untagged-5e043815d553302be2d2/rinkeby_vk_pk.tar.gz), unzip it and save it in the `./zksnark_element` directory.

### Running the tests
Start your prefered ethereum node, `cd tests` and run `python3 test.py` This will
Start your prefered ethereum node, `cd tests`, install the requirements `pip3 install -r requirements.txt` and run `python3 test.py` This will
1. Generate verification keys, proving keys, This step takes a lot of ram and its likely your OS will kill it if you have a bunch of windows open.
2. deploy the contract
3. Deposit 32 ether in 1 ether chunks.
Expand Down
23 changes: 23 additions & 0 deletions contracts/ERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity ^0.4.24;

import "./ERC20Basic.sol";


/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender)
public view returns (uint256);

function transferFrom(address from, address to, uint256 value)
public returns (bool);

function approve(address spender, uint256 value) public returns (bool);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
14 changes: 14 additions & 0 deletions contracts/ERC20Basic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pragma solidity ^0.4.24;


/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* See https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
function totalSupply() public view returns (uint256);
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
86 changes: 0 additions & 86 deletions contracts/MerkelTree.sol

This file was deleted.

142 changes: 119 additions & 23 deletions contracts/Miximus.sol
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
pragma solidity ^0.4.19;

import "../contracts/MerkelTree.sol";
import "../contracts/ERC20.sol";
import "../contracts/Verifier.sol";

contract Miximus is MerkelTree {
mapping (bytes32 => bool) roots;
mapping (bytes32 => bool) nullifiers;
contract Miximus {

struct Mixer {
Mtree MT;
mapping (bytes32 => bool) roots;
mapping (bytes32 => bool) nullifiers;
}

// address(0x0) means mixing Ether
mapping(address => Mixer) mixers;

event Withdraw (address);
Verifier public zksnark_verify;
function Miximus (address _zksnark_verify) {
zksnark_verify = Verifier(_zksnark_verify);
}

function deposit (bytes32 leaf) payable {
require(msg.value == 1 ether);
insert(leaf);
roots[padZero(getRoot())] = true;
function deposit (address _tokenAddress, bytes32 leaf) payable {
if(address(0x0) == _tokenAddress) {
require(msg.value == 1 ether);
}
else {
require(ERC20(_tokenAddress).transferFrom(msg.sender, address(this), 1));
}
insert(_tokenAddress, leaf);
mixers[_tokenAddress].roots[padZero(getRoot(_tokenAddress))] = true;
}

function withdraw (
Expand All @@ -27,35 +40,38 @@ contract Miximus is MerkelTree {
uint[2] c_p,
uint[2] h,
uint[2] k,
uint[] input
uint[] input,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@barryWhiteHat should we document what are the different inputs?

address _tokenAddress
) returns (address) {
address recipient = nullifierToAddress(reverse(bytes32(input[2])));
address recipient = nullifierToAddress(reverse(bytes32(input[2])));
bytes32 root = padZero(reverse(bytes32(input[0]))); //)merge253bitWords(input[0], input[1]);

bytes32 nullifier = padZero(reverse(bytes32(input[2]))); //)merge253bitWords(input[2], input[3]);

require(roots[root]);
require(!nullifiers[nullifier]);
require(mixers[_tokenAddress].roots[root]);
require(!mixers[_tokenAddress].nullifiers[nullifier]);

require(zksnark_verify.verifyTx(a,a_p,b,b_p,c,c_p,h,k,input));
nullifiers[nullifier] = true;
mixers[_tokenAddress].nullifiers[nullifier] = true;

uint fee = input[4];
require(fee < 1 ether);
if (fee != 0 ) {
msg.sender.transfer(fee);

if(_tokenAddress == address(0x0)){
// uint fee = input[4];
// require(fee < 1 ether);
// if (fee != 0 ) {
// msg.sender.transfer(fee);
// }
recipient.transfer(1 ether); // - fee);
}

recipient.transfer(1 ether - fee);
else {
// TODO: fee?
require(ERC20(_tokenAddress).transfer(msg.sender, 1));
}

Withdraw(recipient);
return(recipient);
}

function isRoot(bytes32 root) constant returns(bool) {
return(roots[root]);
}

function nullifierToAddress(bytes32 source) returns(address) {
bytes20[2] memory y = [bytes20(0), 0];
assembly {
Expand Down Expand Up @@ -122,4 +138,84 @@ contract Miximus is MerkelTree {
return bytes32(r);
}


// MerkleTree
uint public tree_depth = 29;
uint public no_leaves = 536870912;
struct Mtree {
uint cur;
bytes32[536870912][30] leaves2;
}

event leafAdded(uint index);

//Merkletree.append(com)
function insert(address _tokenAddress, bytes32 com) internal returns (bool res) {
Mtree MT = mixers[_tokenAddress].MT;
require (MT.cur != no_leaves - 1);
MT.leaves2[0][MT.cur] = com;
updateTree(_tokenAddress); // TODO: this is expensive
leafAdded(MT.cur);
MT.cur++;

return true;
}


function getMerkleProof(address _tokenAddress, uint index) constant returns (bytes32[29], uint[29]) {
Mtree MT = mixers[_tokenAddress].MT;
uint[29] memory address_bits;
bytes32[29] memory MerkleProof;

for (uint i=0 ; i < tree_depth; i++) {
address_bits[i] = index%2;
if (index%2 == 0) {
MerkleProof[i] = getUniqueLeaf(MT.leaves2[i][index + 1],i);
}
else {
MerkleProof[i] = getUniqueLeaf(MT.leaves2[i][index - 1],i);
}
index = uint(index/2);
}
return(MerkleProof, address_bits);
}

function getSha256(bytes32 input, bytes32 sk) constant returns ( bytes32) {
return(sha256(input , sk));
}

function getUniqueLeaf(bytes32 leaf, uint depth) returns (bytes32) {
if (leaf == 0x0) {
for (uint i=0;i<depth;i++) {
leaf = sha256(leaf, leaf);
}
}
return(leaf);
}

function updateTree(address _tokenAddress) internal returns(bytes32 root) {
Mtree MT = mixers[_tokenAddress].MT;
uint CurrentIndex = MT.cur;
bytes32 leaf1;
bytes32 leaf2;
for (uint i=0 ; i < tree_depth; i++) {
uint NextIndex = uint(CurrentIndex/2);
if (CurrentIndex%2 == 0) {
leaf1 = MT.leaves2[i][CurrentIndex];
leaf2 = getUniqueLeaf(MT.leaves2[i][CurrentIndex + 1], i);
} else {
leaf1 = getUniqueLeaf(MT.leaves2[i][CurrentIndex - 1], i);
leaf2 = MT.leaves2[i][CurrentIndex];
}
MT.leaves2[i+1][NextIndex] = (sha256( leaf1, leaf2));
CurrentIndex = NextIndex;
}
return MT.leaves2[tree_depth][0];
}

function getRoot(address _tokenAddress) constant returns(bytes32 root) {
Mtree MT = mixers[_tokenAddress].MT;
root = MT.leaves2[tree_depth][0];
}

}
18 changes: 10 additions & 8 deletions snarkWrapper/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ def hex2int(elements):

def compile(tree_depth):
miximus = "../contracts/Miximus.sol"
MerkelTree = "../contracts/MerkelTree.sol"
Pairing = "../contracts/Pairing.sol"
ERC20 = "../contracts/ERC20.sol"
ERC20Basic = "../contracts/ERC20Basic.sol"
Verifier = "../contracts/Verifier.sol"

compiled_sol = compile_files([Pairing, MerkelTree, Pairing, Verifier, miximus], allow_paths="./contracts")
compiled_sol = compile_files([Pairing, ERC20, ERC20Basic, Pairing, Verifier, miximus], allow_paths="./contracts")

miximus_interface = compiled_sol[miximus + ':Miximus']
verifier_interface = compiled_sol[Verifier + ':Verifier']
Expand Down Expand Up @@ -110,14 +111,15 @@ def deposit(miximus, nullifier, sk, depositAddress):
leaf = miximus.getSha256(nullifier, sk)
print ("leaf: " , w3.toHex(leaf))
print ("null: " , nullifier, "sk: " , sk)

tx_hash = miximus.deposit( leaf, transact={'from': depositAddress, 'gas': 4000000, "value":w3.toWei(1, "ether")})
token_address = '0x0000000000000000000000000000000000000000'
tx_hash = miximus.deposit( token_address, leaf, transact={'from': depositAddress, 'gas': 4000000, "value":w3.toWei(1, "ether")})
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash, 10000)
return(int(tx_receipt["logs"][0]["data"], 16))

def withdraw(miximus, pk):
token_address = '0x0000000000000000000000000000000000000000'
print( w3.eth.getBalance(miximus.address))
tx_hash = miximus.withdraw(pk["a"] , pk["a_p"], pk["b"], pk["b_p"] , pk["c"], pk["c_p"] , pk["h"] , pk["k"], pk["input"] , transact={'from': w3.eth.accounts[0], 'gas': 4000000})
tx_hash = miximus.withdraw(pk["a"] , pk["a_p"], pk["b"], pk["b_p"] , pk["c"], pk["c_p"] , pk["h"] , pk["k"], pk["input"], token_address, transact={'from': w3.eth.accounts[0], 'gas': 4000000})
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash, 10000)

print( w3.eth.getBalance(miximus.address))
Expand All @@ -134,14 +136,14 @@ def genhelloWorld(pk_dir):
pk = helloWorld(c.c_char_p(pk_dir.encode()))

def genWitness(miximus, nullifier, sk, address, tree_depth, fee, pk_dir):

token_address = '0x0000000000000000000000000000000000000000'
path = []
address_bits = []
#tree = miximus.getTree()
#tree_hex = [w3.toHex(x) for x in tree]
root = miximus.getRoot()
root = miximus.getRoot(token_address)

path1, address_bits1 = miximus.getMerkelProof(address, call={"gas":500000})
path1, address_bits1 = miximus.getMerkleProof(token_address, address, call={"gas":500000})
'''
for i in range (0 , tree_depth):
address_bits.append(address%2)
Expand Down
3 changes: 3 additions & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
py-solc
web3
bitstring