Skip to content
forked from klaytn/klaytn

Official Go implementation of the Klaytn protocol(add precompiled contract: bls12-381, mimc hash, poseidon hash)

License

LGPL-3.0, GPL-3.0 licenses found

Licenses found

LGPL-3.0
COPYING.LESSER
GPL-3.0
COPYING
Notifications You must be signed in to change notification settings

snp-labs/zklaytn-dev

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

124Go Report Card CircleCI codecov GoDoc

Klaytn + Precompiled Contract(MiMC7, Poseidon)

Official golang implementation of the Klaytn protocol. Please visit KlaytnDocs for more details on Klaytn design, node operation guides and application development resources.

MiMC

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

Poseidon is mapped to Opcode 0x14.
The Poseidon protocol referred to https://github.com/iden3/go-iden3-crypto/tree/master/poseidon

Require

Go-lang version >= v1.16
Truffle version <= 5.1.25

Reinstall package

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 from Sources

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})

How to Use PreCompiled Contract MiMC7 in Solidity

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)
      }
  }
}

How to Use PreCompiled Contract Poseidon in Solidity

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)
      }
  }
}

How to Use PreCompiled Contract BLS in Solidity

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);
    }
}

About

Official Go implementation of the Klaytn protocol(add precompiled contract: bls12-381, mimc hash, poseidon hash)

Resources

License

LGPL-3.0, GPL-3.0 licenses found

Licenses found

LGPL-3.0
COPYING.LESSER
GPL-3.0
COPYING

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 89.4%
  • Solidity 4.0%
  • C 3.0%
  • JavaScript 2.0%
  • Shell 0.7%
  • Assembly 0.5%
  • Other 0.4%