forked from HarryR/ethsnarks
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added MiMC+EVM contract, which reduces gas cost of hashing
Also added gas reporting for tests, and split MiMC hash into e5/e7
- Loading branch information
HarryR
authored and
HarryR
committed
Jul 29, 2019
1 parent
9d42382
commit 8ffd607
Showing
12 changed files
with
361 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .permutation import mimc, mimc_hash, mimc_hash_md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
# Copyright (c) 2018 Jordi Baylina | ||
# Copyright (c) 2019 Harry Roberts | ||
# License: LGPL-3.0+ | ||
# Based on: https://github.com/iden3/circomlib/blob/master/src/mimc_gencontract.js | ||
|
||
import sys | ||
import json | ||
from binascii import hexlify | ||
|
||
from ..sha3 import keccak_256 | ||
from ..evmasm import * | ||
from ..field import SNARK_SCALAR_FIELD | ||
|
||
from .permutation import mimc_constants | ||
|
||
|
||
def _mimc_opcodes_round(exponent): | ||
# x = input | ||
# k = key | ||
# q = field modulus | ||
# stack upon entry: x q q k q | ||
# stack upon exit: r k q | ||
if exponent == 7: | ||
return [ | ||
DUP(3), # k x q q k q | ||
ADDMOD, # t=x+k q k q | ||
DUP(1), # q t q k q | ||
DUP(0), # q q t q k q | ||
DUP(2), # t q q t q k q | ||
DUP(0), # t t q q t q k q | ||
MULMOD(), # a=t^2 q t q k q | ||
DUP(1), # q a q t q k q | ||
DUP(1), # a q a q t q k q | ||
DUP(0), # a a q a q t q k q | ||
MULMOD, # b=t^4 a q t q k q | ||
MULMOD, # c=t^6 t q k q | ||
MULMOD # r=t^7 k q | ||
] | ||
elif exponent == 5: | ||
return [ | ||
DUP(3), # k x q q k q | ||
ADDMOD, # t=x+k q k q | ||
DUP(1), # q t q k q | ||
DUP(0), # q q t q k q | ||
DUP(2), # t q q t q k q | ||
DUP(0), # t t q q t q k q | ||
MULMOD(), # a=t^2 q t q k q | ||
DUP(0), # a a q t q k q | ||
MULMOD, # b=t^4 t q k q | ||
MULMOD # r=t^5 k q | ||
] | ||
|
||
|
||
def mimc_contract_opcodes(exponent): | ||
assert exponent in (5, 7) | ||
tag = keccak_256(f"MiMCpe{exponent}(uint256,uint256)".encode('ascii')).hexdigest() | ||
|
||
# Ensuring that `exponent ** n_rounds` > SNARK_SCALAR_FIELD | ||
n_rounds = 110 if exponent == 5 else 91 | ||
constants = mimc_constants(R=n_rounds) | ||
|
||
yield [PUSH(0x44), # callDataLength | ||
PUSH(0), # callDataOffset | ||
PUSH(0), # memoryOffset | ||
CALLDATACOPY, | ||
PUSH(1<<224), | ||
PUSH(0), | ||
MLOAD, | ||
DIV, | ||
PUSH(int(tag[:8], 16)), # function selector | ||
EQ, | ||
JMPI('start'), | ||
INVALID] | ||
|
||
yield [LABEL('start'), | ||
PUSH(SNARK_SCALAR_FIELD), # q | ||
PUSH(0x24), | ||
MLOAD] # k q | ||
|
||
yield [ | ||
PUSH(0x04), # 0x04 k q | ||
MLOAD # x k q | ||
] | ||
|
||
for c_i in constants: | ||
yield [ | ||
DUP(2), # q r k q | ||
DUP(0), # q q r k q | ||
DUP(0), # q q q r k q | ||
SWAP(3), # r q q q k q | ||
PUSH(c_i), # c r q q q k q | ||
ADDMOD, # c+r q q k q | ||
] | ||
yield _mimc_opcodes_round(exponent) | ||
|
||
# add k to result, then return | ||
yield [ | ||
ADDMOD, # r+k | ||
PUSH(0), # r+k 0 | ||
MSTORE, # | ||
PUSH(0x20), # 0x20 | ||
PUSH(0), # 0 0x20 | ||
RETURN | ||
] | ||
|
||
|
||
def mimc_abi(exponent): | ||
assert exponent in (5, 7) | ||
return [{ | ||
"constant": True, | ||
"inputs": [ | ||
{ | ||
"name": "in_x", | ||
"type": "uint256" | ||
}, | ||
{ | ||
"name": "in_k", | ||
"type": "uint256" | ||
} | ||
], | ||
"name": f"MiMCpe{exponent}", | ||
"outputs": [ | ||
{ | ||
"name": "out_x", | ||
"type": "uint256" | ||
} | ||
], | ||
"payable": False, | ||
"stateMutability": "pure", | ||
"type": "function" | ||
}] | ||
|
||
|
||
def mimc_contract(exponent): | ||
gen = Codegen() | ||
for _ in mimc_contract_opcodes(exponent): | ||
gen.append(_) | ||
return gen.createTxData() | ||
|
||
|
||
def main(*args): | ||
if len(args) < 2: | ||
print("Usage: %s <abi|contract> <exponent> [outfile]" % (args[0],)) | ||
return 1 | ||
command = args[1] | ||
exponent = int(args[2]) | ||
if exponent not in (5, 7): | ||
print("Error: exponent must be 5 or 7") | ||
return 2 | ||
outfile = sys.stdout | ||
if len(args) > 3: | ||
outfile = open(args[3], 'wb') | ||
if command == "abi": | ||
outfile.write(json.dumps(mimc_abi(exponent)) + "\n") | ||
return 0 | ||
elif command == "contract": | ||
data = mimc_contract(exponent) | ||
if outfile == sys.stdout: | ||
data = '0x' + hexlify(data).decode('ascii') | ||
outfile.write(data) | ||
return 0 | ||
else: | ||
print("Error: unknown command", command) | ||
if outfile != sys.stdout: | ||
outfile.close() | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main(*sys.argv)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
try: | ||
# pysha3 | ||
from sha3 import keccak_256 | ||
except ImportError: | ||
# pycryptodome | ||
from Crypto.Hash import keccak | ||
keccak_256 = lambda *args: keccak.new(*args, digest_bits=256) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,21 @@ | ||
{ | ||
"name": "ethsnarks", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "zkSNARKS for Ethereum", | ||
"main": "truffle.js", | ||
"repository": "https://github.com/HarryR/ethsnarks.git", | ||
"author": "[email protected]", | ||
"license": "LGPL-3.0+", | ||
"dependencies": { | ||
"solc": "^0.5.9", | ||
"truffle": "^5.0.22" | ||
"rlp": "^2.2.3", | ||
"solc": "^0.5.10", | ||
"truffle": "^5.0.29" | ||
}, | ||
"devDependencies": { | ||
"ganache-cli": "^6.4.4", | ||
"solhint": "^1.5.1", | ||
"solidity-coverage": "^0.5.11" | ||
"solidity-coverage": "^0.5.11", | ||
"eth-gas-reporter": "^0.2.4" | ||
}, | ||
"scripts": { | ||
"compile": "truffle compile", | ||
|
Oops, something went wrong.