This commit is contained in:
Joshua Gancher 2016-07-28 11:09:09 -04:00
parent eb5c089456
commit 9eba126e30
9 changed files with 389 additions and 0 deletions

1
zoe/chain/pass.conf Normal file
View File

@ -0,0 +1 @@
parity

44
zoe/chain/poa_chain.json Normal file
View File

@ -0,0 +1,44 @@
{
"name": "Morden",
"engine": {
"BasicAuthority": {
"params": {
"gasLimitBoundDivisor": "0x0400",
"durationLimit": "0x0d",
"authorities" : ["0x323ac74f0de6291b23d100b8400245a0c8ac7933"]
}
}
},
"params": {
"accountStartNonce": "0x0100000",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x42"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x00006d6f7264656e",
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x493E00"
},
"nodes": [
"enode:////c2328c3e7857106585dbb59b712ac2ab9443d4f0b55b77451fbf33c0dda58b882f0683c4c9222cbf8d1d6893e7f926d487630810202a2c75ec6dd996dbe84715@192.168.0.12:30305"
],
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "nonce": "1048576", "builtin": { "name": "zkSNARK", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"323ac74f0de6291b23d100b8400245a0c8ac7933": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" },
"222b3fe688a9d8bdf03f1993df29f3804ac0bd9c": { "balance": "100", "nonce": "1048576" }
}
}

104
zoe/contract/mixer_v2.sol Normal file
View File

@ -0,0 +1,104 @@
contract SnarkPrecompile {
function verify_proof (bytes, bytes, bytes) returns (bool);
}
contract Mixer {
mapping (bytes32 => bool) public serials;
mapping (bytes32 => bool) public roots;
SnarkPrecompile zksnark = SnarkPrecompile(0x0000000000000000000000000000000000000005);
struct Mtree {
uint cur;
bytes32[16] leaves;
}
Mtree public MT;
bytes public vk;
function Mixer(bytes _vk) {
vk = _vk;
MT.cur = 0;
for (uint i = 0; i < 16; i++)
MT.leaves[i] = 0x0;
}
//Merkletree.append(com)
function insert(bytes32 com) returns (bool res) {
if (MT.cur == 16) {
return false;
}
MT.leaves[MT.cur] = com;
MT.cur++;
return true;
}
function getLeaves() constant returns (bytes32[16]) {
return MT.leaves;
}
function getTree() constant returns (bytes32[32] tree) {
//bytes32[32] memory tree;
uint i;
for (i = 0; i < 16; i++)
tree[16 + i] = MT.leaves[i];
for (i = 16 - 1; i > 0; i--)
tree[i] = sha256(tree[i*2], tree[i*2+1]);
return tree;
}
//Merkletree.root()
function getRoot() constant returns(bytes32 root) {
root = getTree()[1];
}
function deposit(bytes32 com) returns (bool res) {
if (msg.value != 1 ether) {
msg.sender.send(msg.value);
return false;
}
if (!insert(com)) {
msg.sender.send(msg.value);
return false;
}
bytes32 rt = getRoot();
roots[rt] = true;
return true;
}
function withdraw(bytes32 serial, address addr, bytes32 rt, bytes32 mac, bytes proof) returns (bool success) {
success = false;
bytes20 addr_byte = bytes20(addr);
bytes memory pub = new bytes(128);
uint i;
for (i = 0; i < 32; i++) pub[i] = serial[i];
for (i = 0; i < 20; i++) pub[32 + i] = addr_byte[i];
for (i = 20; i < 32; i++) pub[32 + i] = 0;
for (i = 0; i < 32; i++) pub[32*2 + i] = rt[i];
for (i = 0; i < 32; i++) pub[32*3 + i] = mac[i];
if (roots[rt] == true) {
if (!serials[serial]) {
if (!zksnark.verify_proof(vk, proof, pub)) {
return false;
}
serials[serial] = true;
if (!addr.send(1 ether)) {
throw;
}
else {
success = true;
}
}
else {
return;
}
}
else {
return;
}
}
function dummy() { }
}

View File

@ -0,0 +1,210 @@
var Web3 = require('web3');
var solc = require('solc');
var fs = require('fs');
var async = require('async');
var utils = require('ethereumjs-util');
var promptly = require('promptly');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545/'));
web3.eth.defaultAccount = web3.eth.accounts[1];
// All of below are generated by keygen.rs and spend.rs; run those and paste values here accordingly
var serial = "0x0c6dee6423046fbdd3c5e3dd60b5e560b2e6cf178e025bfc24660a4bee6c5e80";
var address = "0x222b3fe688a9d8bdf03f1993df29f3804ac0bd9c";
var root = "0x5c2f2c21288d6a17b6078e74f0e4fd9bd87db2bb55f7532bc40ad6efe1e88058";
var mac = "0xe7e5d0f1b4e2e51c4bb8fa2cee75594219f302883de45b5978f84909b9466958";
var proof = "0x3040f4ffbbe456aa201d976ed8994cdc5aea6adacd088157ac410448903a413d0040dfc3a2df37481f4d25f827a4f1d54d7fb64a491c892e2d739211d1f7abb321309878760dd92d630693a49e988dd0bfb0f81d039853bd2f89a168488c1c0a8b10148c66bc3d0e173d7c163fa008645566461e55dc167dc34ec65b83280da2831030e8021fe0c199769344ecd209c38a845649a148a65d9867c7632ce3b2a5d24f1cd94a3d94710f84470188a0b9b15aace4f1bc1fcf303a2f667edfac7ba912841296643e820df5e40a92b0cda9ab7a7efc954bc0751007f0ad2779d803ef4a7125db11f68c2b538d8a49f3e10c79f02f4c0b88899503c8cbd1b3ccd29500eca3183031fdbee5be2f274a4a7dc2800a4b9492f384f3bd0684e28650f96f1a86106c1528c20be12fe60c40774ee2ad9d156cbad14ab2e78c7ebf6eb3d2e08ff37e692c3029a3aa110fa58b6b8ca32d8d5f1c72042647e1ed87fc7f741752907690945506acb9908437759b512c2a15fa0660f5c4f04d45e2600a51eaae9f950061e31a2c3076dd0484062e16c464f2d67ffcbc6fd5fb402f09d938c7cdc79aafc787c1fb1d5bb1f414e798485b0201cd9915063310b21f4b53f42d78a5edf2dc6a4d73570b3080840c1c2ab4ae252dc26fbf5a2a9969a07d3d3b875c92cfb2d789567009f021c1da276778a84a2cf745563bacd586995ff7a54725d1076caa77c084e0bd3b26304e0481adbd1afd567893023c5fbab97001486fab36201445f9b00c9beeaac6145e169d42101a5fa9dc8ccca45aca4c0152401f843c64f149f2782120ee74c120";
var DEPOSIT_COMMITMENTS = [ '0x5c5cf0337d3f0e860eb5d8f14434a0e5c8b6115461c85ecea2be7355a92807b7',
'0x010091a76eea67b6291dbf4ad41f83aa3b7e130e8b3447184b884cd379749b2f',
'0xce97f5712b8e6e4b197f2962fae8d6bfa1d091d86c9294c1a14e3a5a2ead583c',
'0xa58e6e9ec234a104a29f5f1ee97b4be19c3fc9b4c707d520ef9bafebecffad65',
'0x1663bc9f9076c6469afbb6c8ada4e5d0c4f1a365710dec743c9706e0b719be71',
'0x2d31fb6a8c6005acacbfecd88a8561eb575cc72b29fdee02ee19d6f6b293e385',
'0x52fa0328f9a48452c826e2a126cccc6762468b1d39946be136dcb71abc504435',
'0xbcc08e71b64b319ed7d6bcdf960cb0309b5ae6d6406a89ac7487e37b7c262c03',
'0x94737b0d015c49da7290a3d762b85eac4eb7d6d74246f664dd702e1b976523c9',
'0x1ec3628d2c96b2dfff2bdadf1e52c52d6ab1a874ff51cffa652c979c8fcb9ec7',
'0x1eca9c446e23557d186fb3e32d5f28723b03a412321a89866e2f09f8d8353114',
'0x49344fe91ceea310053580b4eb5c2039f7dd095d59d8e08521ab38efa03b8ace',
'0x75633c203d379f55be3e170ac8fa1adac93838fd7420db81cda60477eb3e77a3',
'0xc65903a6f4ff856ec5c0e959409f2f555dbbc6d43e352a5f0b20a18bb391dffd',
'0x46104418aa1cf5cf756201031201764cc7770e0b2f842111b126823df3ba863d',
'0x98a3ddb12a853e8ca5aab5d60ee92cadd9c0f1eaaca7497d2e722c91fac23dc1'];
var vk = web3.toBigNumber( "0x30c464bab4bbde5c49b1f1271d7217b04a8e71b1a656131f1bff32d91702582c23b039634037f16ca6bca5b4bbc36cdb0344069ed57a51ac2407be7b06c1672d040973e931628bdd507e5b8b1073cd709ff6b3eccf3c8eabfa1997f68f99582b25a7a7115f0ea1342b26277ffe08661f85a578e9deddd985d1590aa02cef8f4d00309960c6d47c70eeb86b5722964995bbc6a9b3018570ee634df92d65ba73fc192c71097e42607bed6a3ab07007d157923e416a864837de845dc8fa8e67fc582b0a30d499dac34bd084cc0e287e23671d99f974e7b29e3c5299d51bfb6161965c6f0bb7dd19ae3b14444d7f670af9b24bee31d71a417a97469b70bb65501107890127b774207b2457caf81f0f5b0b86710633695b27cf36bb0520f51be8fff3506a27d5c667b46f8e34b5595a37dc27084bb48b943749ab2cb9f3d97647ebb6812a2d30676d5b8835aaf59ae2d5b3b143794fb35e048138679be62c4aad68408a219616037ef3b64ab5281be221a3f012f75c9192266a0b6710baf55776c40654ae170377777971f672c537f4c1b75d165d9e20ebb52e46ed8fcf8fb3b23334ad86d82238733380ad2643f940ab696b546b3503b3ba32c56c74f8f8ab904c98aac463003079696da0d939d2fef2c2fbdcfbc7fec533e92459b0f8a7b97e1539538836c92bb570da446f191a48bc9b42c9f1384473dd69cdc9e59b146ba84d6afeb4e4512f30d294a5ebd2c207255558e50cbabd1c148537bd0ca57286fcdea16cfff6746b0c611a373cdc31ea765861a4e8b33078f3e37b540be3de867bac9786ef62d7ac296faca15d6ae864d295264a209223d6859fea8a7046285547c0dea497df06342d326387ee3c516e1b97e96d7e858dc5765accebf69d909b89fbe8540fe5815c2c3090a7fa676a712a41c93ea3d514269ca0532fa1ab6dd833f7d98300e53156172bc881a2472b966e864bf6cd2d1c6b074a197e4726cc446562915d4f376bad7006395ff249aaf972ff2bd20c3bd1e82eaa51d0b0e886bd5348ed708fd321afbd1dd05fa825fc6fde990a22b16e101d42957bc6214011fa105d0b628e13e4d8ba28307f4ab55ece71f03bde396a6632cca545e9f06f7d2ced59be3a492adcf68e5029a695220b60219a73d338a8d236a898eb1255f21c7a317aac9a558f5f56b15407350a350a300a310a320a330a340a350a30dee3543e7cec57cebf29ea0dd1b6a9fb39732797652d727dc6932d4422ac5b23433b5b5d1094f393bec041f222e7bfcc5f2087e029af4ab7f128b3a16d08e02130ac86e21ff74d0ba055fa99c67ccc033032123c69a736ad63856fa4ee92679c1863254bdf115f69cd336669e443baa9133971813f23736f84602b3be31541ec213033c5ab44058e930ff23dbbdafd2ffe255d0d04eb583557a8f8994729977ff623f52807bc331832d6d4d2348d5b9ebb080677a1d1830d287ad5e1bab260395a1f30b546b079b7a3545dcf3d473b5b2101f4657341c3aa7f0648c6fa9d0d3747c705605896d0e2a6620603cce3ccd77635585142139b37650222478f34056c57df1a30710a5108eca94ef48349ff759f3c20fdfd16060b445e665c8b8c0944d666da187563d52f5575648d4ebd27e786a169ff26a5bd5481c808417e822e0d8004ce17");
var contract_code = fs.readFileSync('./mixer_v2.sol');
var output = solc.compile(contract_code.toString());
//console.log('output:', output);
var MixerABI = JSON.parse(output.contracts['Mixer'].interface);
//console.log('MixerABI:', JSON.stringify(MixerABI));
var MixerContract = web3.eth.contract(MixerABI);
//console.log('MixerContract:', MixerContract);
var MixerInstance;
//var mixerTest = MixerContract.new(
MixerContract.new(vk,
{
from: web3.eth.accounts[1],
data: '0x' + output.contracts['Mixer'].bytecode,
gas: 4700000
}, function (e, contract){
//console.log(e);
/*
TODO: complain about very strange behavior http://ethereum.stackexchange.com/questions/6731/should-callbacks-be-called-twice-from-both-mycontract-new-and-mycontract-myfunct
*/
if (contract.address !== undefined) {
//console.log('mixerTest.new e:', e);
//console.log('mixerTest.new contract:', contract);
var contract_addy = contract.address;
//console.log('contract_addy:', contract_addy);
/*
// timeout is needed or tx fails in parity
setTimeout(function() {
testDeposit(contract_addy);
}, 5000);
*/
MixerInstance = MixerContract.at(contract_addy);
var i = 0;
async.mapSeries(DEPOSIT_COMMITMENTS, function(cm, cb) {
sendDeposit(cm, function(err, result) {
setTimeout(function() {
return cb();
}, 50);
})
}, function() {
var f = 0;
f = function() {
console.log('Getting root');
r = MixerInstance.getRoot();
if (r != "0x5c2f2c21288d6a17b6078e74f0e4fd9bd87db2bb55f7532bc40ad6efe1e88058") {
console.log("Bad root: "+r);
MixerInstance.dummy.sendTransaction({from: web3.eth.accounts[1]}, function(err, res) {
return setTimeout(f, 500);
});
}
console.log("Good root!");
sendWithdraw(serial, address, root, mac, proof, function(e, res) {
//console.log('res = ' , res);
console.log("Withdrawing..");
for (var j = 0; j < 5; j++) {
MixerInstance.dummy.sendTransaction({from: web3.eth.accounts[1]}, function(err, res) {
return setTimeout(function() {}, 500);
});
}
printTree(MixerInstance);
printBalance(MixerInstance.address);
printBalance(address);
});
};
f();
});
} else {
return;
}
});
function sendDeposit(commitment_hex_str, cb_func) {
//var commitment = utils.sha256("asdf" + Math.random()).toString('hex');
//commitment = web3.toBigNumber('0x' + commitment);
//console.log('2nd deposit commitment:', commitment);
console.log("Depositting...");
MixerInstance.deposit.sendTransaction(
commitment_hex_str,
{from:web3.eth.accounts[1], value: web3.toWei('1', 'ether'), gas: 500000},
cb_func
);
}
function sendWithdraw(_serial, _addr, _rt, _mac, _proof, cb_func) {
MixerInstance.withdraw.sendTransaction(
_serial,
_addr,
_rt,
_mac,
_proof,
{from:web3.eth.accounts[1], gas: 2000000},
cb_func
)
}
function printBalance(addy) {
console.log('getBalance addy:', addy);
//var bal = web3.fromWei(web3.eth.getBalance(addy), 'ether').toNumber();
var bal = web3.eth.getBalance(addy).toNumber();
console.log('mixer contract balance:', bal);
}
function printTree(mixer_instance) {
//var merkle_tree = mixerInstance.MT.leaves;
/*var merkle_tree = mixer_instance.getTree();
console.log('merkle_tree:', merkle_tree);
var merkle_leaves = mixer_instance.getLeaves();
console.log('merkle_leaves:', merkle_leaves);*/
var merkle_root = mixer_instance.getRoot();
console.log('Current Merkle root:', merkle_root);
//console.log('merkle_tree:', merkle_tree.toJSON());
}
function getAuthPath(commitment, merkle_tree) {
console.log('getAuthPath commitment:', commitment)
var com_index = merkle_tree.indexOf(commitment);
console.log('com_index:', com_index);
return com_index;
}
function getLeafIndex(commitment, merkle_leaves) {
console.log('getLeafIndex commitment:', commitment)
var com_index = merkle_leaves.indexOf(commitment);
console.log('com_index:', com_index);
var com_index_binary = com_index.toString(2);
var leaf_index = String(com_index_binary + "0000").slice(0, 4); // zero pad on right
return com_index;
}

14
zoe/notes/instructions Normal file
View File

@ -0,0 +1,14 @@
to get running from scratch (ie, no .parity folder):
1.call "./target/debug parity account new" twice
2. in poa_chain.json, set "authorities" : [(first account here) "0xacctaddr"]
add two lines to accounts section, below the precompiles (do not include 0x)
"acctaddr1": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" },
"acctaddr2": { "balance": "100", "nonce": "1048576" }
3. run command in command file
./target/debug/parity --chain poa_chain.json --dapps-port 8090 --jsonrpc-cors http://ethereum.github.io --author acctaddr1 --unlock acctaddr1 --password pass.conf --reseal-on-txs all --force-sealing
4. edit .js file in contract folder, and make sure you call everything from acctaddr1
(if things don't work for no reason, try adding more gas)
to generate proofs, go to tinysnark folder and run "cargo run --example spend.rs"

14
zoe/notes/instructions~ Normal file
View File

@ -0,0 +1,14 @@
to get running from scratch (ie, no .parity folder):
1.call "./target/debug parity account new" twice
2. in poa_chain.json, set "authorities" : [(first account here) "0xacctaddr"]
add two lines to accounts section, below the precompiles (do not include 0x)
"acctaddr1": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" },
"acctaddr2": { "balance": "100", "nonce": "1048576" }
3. run command in command file
./target/debug/parity --chain poa_chain.json --dapps-port 8090 --jsonrpc-cors http://ethereum.github.io --author acctaddr1 --unlock acctaddr1 --password pass.conf --reseal-on-txs all --force-sealing
4. edit .js file in contract folder, and make sure you call everything from acctaddr1
(if things don't work for no reason, try adding more gas)
to generate proofs, go to tinysnark folder and run "cargo run --example spend.rs"

1
zoe/parity Submodule

@ -0,0 +1 @@
Subproject commit ce00c13c7a2482c4d9405483e769c01b3f04ab4e

1
zoe/tinysnark Submodule

@ -0,0 +1 @@
Subproject commit 4a6830b5c4fa938cb48508638a7c5ffeda5dbd48