Official golang implementation of the Klaytn protocol. Please visit KlaytnDocs for more details on Klaytn design, node operation guides and application development resources.
MiMC7 is mapped to Opcode 0x13.
Detail MiMC protocol : https://eprint.iacr.org/2016/492.pdf
Detail MiMC7 protocol : https://iden3-docs.readthedocs.io/en/latest/_downloads/a04267077fb3fdbf2b608e014706e004/Ed-DSA.pdf
MiMC7 algorithm :
// global variables
const ORDER = 21888242871839275222246405745257275088548364400416034343698204186575808495617
let rc = []
rc[0] = keccak256("mimc7_seed")
for i = 1 to i <= 91
rc[i] = keccak256(rc[i - 1])
// Receives a arbitrary inputs and calculate the MiMC7 hash function.
// message & key mapping As follows.
// message : before mimc7round result(in first time, that is first input data)
// key : next input data
function Mimc7(inputs)
if len(inputs) <= 1 then
return mimc7round(inputs[0], inputs[0])
else
let output = input[0]
for i = 1 to i < len(inputs) do
output = Mimc7round(output, input[i])
return output
endfor
endif
// Receives a message and a key pair and calculate the MiMC7 hash function.
function Mimc7round(m, key)
let c = (m + key)^7 mod ORDER // round 1
for i = 2 to i < 92 do // round 2 ~ 91
c = (c + key + rc[i])^7 mod ORDER
endfor
return (c + key + m + key) mod ORDER
Poseidon is mapped to Opcode 0x14.
The Poseidon protocol referred to https://github.com/iden3/go-iden3-crypto/tree/master/poseidon
Go-lang version >= v1.16
Truffle version <= 5.1.25
Changed Go-lang version :
Downloads go-lang package in https://go.dev/dl/ then
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf ./go1.*.*.****-****.tar.*
Changed Truffle version :
npm uninstall -g truffle
npm install -g truffle@5.1.23
Building the Klaytn node binaries as well as utility tools, such as kcn
, kpn
, ken
, kbn
, kscn
, kspn
, ksen
, kgen
, homi
and abigen
requires
both a Go (version 1.14.1 or later) and a C compiler. You can install them using
your favorite package manager.
Once the dependencies are installed, run
make all (or make {kcn, kpn, ken, kbn, kscn, kspn, ksen, kgen, homi, abigen})
The input data must padded the remaining left side of 32bytes to "0". (ex 0x01 -> 0x0000000000000000000000000000000000000000000000000000000000000001)
If solidity version order than v0.5.0, use "gas" instead of "gas()" as the first factor in the call function.
pragma solidity >=0.5.0
function callmimc(bytes32[] memory data) public returns (bytes32 result) {
uint256 len = data.length*32;
assembly {
let memPtr := mload(0x40)
let success := call(gas(), 0x13, 0, add(data, 0x20), len, memPtr, 0x20)
//solc -v < 0.5.0 let success := call(gas, 0x13, 0, add(data, 0x20), len, memPtr, 0x20)
switch success
case 0 {
revert(0,0)
} default {
result := mload(memPtr)
}
}
}
The input data must padded the remaining left side of 32bytes to "0". (ex 0x01 -> 0x0000000000000000000000000000000000000000000000000000000000000001)
If solidity version order than v0.5.0, use "gas" instead of "gas()" as the first factor in the call function.
pragma solidity >=0.5.0
function callposeidon(bytes32[] memory data) public returns (bytes32 result) {
uint256 len = data.length*32;
assembly {
let memPtr := mload(0x40)
let success := call(gas(), 0x14, 0, add(data, 0x20), len, memPtr, 0x20)
//let success := call(gas, 0x14, 0, add(data, 0x20), len, memPtr, 0x20)
switch success
case 0 {
revert(0,0)
} default {
result := mload(memPtr)
}
}
}
contract Bls {
event showbytes32(bytes32 output);
event showbytes32arr(bytes32[] output);
// General Bls12-381 format
// each elements are 48 bytes
// g1Affine : 96 bytes (2 elements) -> g1.x, g1.y
// g2Affine : 192 bytes (4 elements) -> g2.x0, g2.x1, g2.y0, g2.y1
// gt : 576 bytes (12 elements) -> gt.c0, gt.c1 ... gt.c11
// Go-eth Bls12-381 format
// g1,g2's each elements are 64 bytes -> append 16 bytes of 0 to the front
// g1 : 128 bytes -> [ concat([0u8;16], g1.x[:16]), g1.x[16:48], concat([0u8;16], g1.y[:16]), g1.y[16:48] ]
// g2 : 256 bytes -> in the same way as g1
// gt : 576 bytes -> [ gt.c0[:32], concat(gt.c0[32:], gt.c1[:16]), gt.c1[16:], .... ]
function ParingCmp(bytes32[] memory inputs) public returns (bytes32 result){
// result = (e(a,A) + e(b,B) + e(c,C)... == gt)
// inputs index elements
// 0 ~ 12*k-1 [(g1, g2)] // k : num of g1,g2 pair
// 12*k ~ gt
assembly{
let len := mload(inputs)
let memPtr := mload(0x40)
let success := call(gas(), 0x17, 0, add(inputs, 0x20), mul(len, 0x20), memPtr, 0x20)
switch success case 0 {
revert(0, 0)
}
default {
result := mload(memPtr)
}
}
emit showbytes32(result);
}
function GtAdd(bytes32[] memory inputs) public returns (bytes32[] memory result){
// result = (gt_1 + gt_2)
// inputs index elements
// 0 ~ 17 gt_1
// 18 ~ gt_2
assembly{
let len := mload(inputs)
result := mload(0x40)
mstore(result, 0x12)
let success := call(gas(), 0x16, 0, add(inputs, 0x20), mul(len, 0x20), add(result, 0x20), mul(0x12, 0x20))
switch success case 0 {
revert(0, 0)
}
mstore(0x40, add(result, add(0x20, mul(0x12, 0x20))))
}
emit showbytes32arr(result);
}
function GtMul(bytes32[] memory inputs) public returns (bytes32[] memory result){
// result = (gt^scaler) // scaler : 32 bytes
// inputs index elements
// 0 ~ 17 gt
// 17 ~ scaler
assembly{
let len := mload(inputs)
result := mload(0x40)
mstore(result, 0x12)
let success := call(gas(), 0x15, 0, add(inputs, 0x20), mul(len, 0x20), add(result, 0x20), mul(0x12, 0x20))
switch success case 0 {
revert(0, 0)
}
mstore(0x40, add(result, add(0x20, mul(0x12, 0x20))))
}
emit showbytes32arr(result);
}
}