Browse Source

Absorb circuit implemented

master
arnaucube 2 years ago
parent
commit
7cd26a6a54
4 changed files with 150 additions and 7 deletions
  1. +32
    -0
      circuits/keccak256.circom
  2. +57
    -0
      go-keccak256-bits-impl/keccak_test.go
  3. +5
    -0
      test/circuits/absorb_test.circom
  4. +56
    -7
      test/keccak256.js

+ 32
- 0
circuits/keccak256.circom

@ -65,6 +65,38 @@ template KeccakfRound(r) {
}
}
template Absorb() {
var blockSizeBytes=136;
signal input s[25*64];
signal input block[blockSizeBytes*8];
signal output out[25*64];
var i;
var j;
component aux[blockSizeBytes/8];
component newS = Keccakf();
for (i=0; i<blockSizeBytes/8; i++) {
aux[i] = XorArray(64);
for (j=0; j<64; j++) {
aux[i].a[j] <== s[i*64+j];
aux[i].b[j] <== block[i*64+j];
}
for (j=0; j<64; j++) {
newS.in[i*64+j] <== aux[i].out[j];
}
}
// fill the missing s that was not covered by the loop over
// blockSizeBytes/8
for (i=(blockSizeBytes/8)*64; i<25*64; i++) {
newS.in[i] <== s[i];
}
for (i=0; i<25*64; i++) {
out[i] <== newS.out[i];
}
}
template Keccakf() {
signal input in[25*64];
signal output out[25*64];

+ 57
- 0
go-keccak256-bits-impl/keccak_test.go

@ -2,6 +2,7 @@ package keccak
import (
"encoding/hex"
"fmt"
"testing"
"github.com/ethereum/go-ethereum/crypto"
@ -107,6 +108,62 @@ func TestKeccakf(t *testing.T) {
13518516210247555620})
}
func printBytes(name string, b []byte) {
fmt.Printf("%s\n", name)
for _, v := range b {
fmt.Printf("\"%v\", ", v)
}
fmt.Println("")
}
func printU64Array(name string, b []uint64) {
fmt.Printf("%s\n", name)
for _, v := range b {
fmt.Printf("\"%v\", ", v)
}
fmt.Println("")
}
func TestAbsorb(t *testing.T) {
s, _ := newS()
block := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128}
// printU64Array("s", bitsToU64Array(s[:]))
// printBytes("block", block[:])
absorbed := absorb(s, bytesToBits(block))
// printU64Array("absorbed", bitsToU64Array(absorbed[:]))
qt.Assert(t, bitsToU64Array(absorbed[:]), qt.DeepEquals,
[]uint64{8342348566319207042, 319359607942176202, 14410076088654599075,
15666111399434436772, 9558421567405313402, 3396178318116504023,
794353847439963108, 12717011319735989377, 3503398863218919239,
5517201702366862678, 15999361614129160496, 1325524015888689985,
11971708408118944333, 14874486179441062217, 12554876384974234666,
11129975558302206043, 11257826431949606534, 2740710607956478714,
15000019752453010167, 15593606854132419294, 2598425978562809333,
8872504799797239246, 1212062965004664308, 5443427421087086722,
10946808592826700411})
absorbed = absorb(absorbed, bytesToBits(block))
// printU64Array("absorbed", bitsToU64Array(absorbed[:]))
qt.Assert(t, bitsToU64Array(absorbed[:]), qt.DeepEquals,
[]uint64{8909243822027471379, 1111840847970088140,
12093072708540612559, 11255033638786021658, 2082116894939842214,
12821085060245261575, 6901785969834988344, 3182430130277914993,
2164708585929408975, 14402143231999718904, 16231444410553803968,
1850945423480060493, 12856855675247400303, 1137248620532111171,
7389129221921446308, 12932467982741614601, 1350606937385760406,
10983682292859713641, 10305595434820307765, 13958651111365489854,
17206620388135196198, 4238113785249530092, 7230868147643218103,
603011106238724524, 16480095441097880488})
}
func TestFinal(t *testing.T) {
b := make([]byte, 32)
for i := 0; i < len(b); i++ {

+ 5
- 0
test/circuits/absorb_test.circom

@ -0,0 +1,5 @@
pragma circom 2.0.0;
include "../../circuits/keccak256.circom";
component main = Absorb();

+ 56
- 7
test/keccak256.js

@ -350,12 +350,15 @@ describe("keccakfRound test", function () {
describe("keccakf test", function () {
this.timeout(100000);
it ("keccakf 1 (testvector generated from go)", async () => {
let cir;
before(async () => {
// const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
const cir = await c_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
cir = await c_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
await cir.loadConstraints();
console.log("n_constraints", cir.constraints.length);
});
it ("keccakf 1 (testvector generated from go)", async () => {
const input = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];
const expectedOut = strsToBigInts(["9472389783892099349", "2159377575142921216", "17826682512249813373", "2325963263767348549", "15086930817298358378", "11661812091723830419", "3517755057770134847", "5223775837645169598", "933274647126506074", "3451250694486589320", "825065683101361807", "6192414258352188799", "14426505790672879210", "3326742392640380689", "16749975585634164134", "17847697619892908514", "11598434253200954839", "6049795840392747215", "8610635351954084385", "18234131770974529925", "15330347418010067760", "12047099911907354591", "4763389569697138851", "6779624089296570504", "15083668107635345971"]);
@ -371,11 +374,6 @@ describe("keccakf test", function () {
});
it ("keccakf 2 (testvector generated from go)", async () => {
// const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
const cir = await c_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
await cir.loadConstraints();
console.log("n_constraints", cir.constraints.length);
const input = strsToBigInts(["9472389783892099349", "2159377575142921216", "17826682512249813373", "2325963263767348549", "15086930817298358378", "11661812091723830419", "3517755057770134847", "5223775837645169598", "933274647126506074", "3451250694486589320", "825065683101361807", "6192414258352188799", "14426505790672879210", "3326742392640380689", "16749975585634164134", "17847697619892908514", "11598434253200954839", "6049795840392747215", "8610635351954084385", "18234131770974529925", "15330347418010067760", "12047099911907354591", "4763389569697138851", "6779624089296570504", "15083668107635345971"]);
const expectedOut = strsToBigInts(["269318771259381490", "15892848561416382510", "12485559500958802382", "4360182510883008729", "14284025675983944434", "8800366419087562177", "7881853509112258378", "9503857914080778528", "17110477940977988953", "13825318756568052601", "11460650932194163315", "13272167288297399439", "13599957064256729412", "12730838251751851758", "13736647180617564382", "5651695613583298166", "15496251216716036782", "9748494184433838858", "3637745438296580159", "3821184813198767406", "15603239432236101315", "3726326332491237029", "7819962668913661099", "2285898735263816116", "13518516210247555620"]);
@ -390,3 +388,54 @@ describe("keccakf test", function () {
assert.deepEqual(stateOutU64, expectedOut);
});
});
describe("absorb test", function () {
this.timeout(100000);
let cir;
before(async () => {
// const cir = await wasm_tester(path.join(__dirname, "circuits", "keccakf_test.circom"));
cir = await c_tester(path.join(__dirname, "circuits", "absorb_test.circom"));
await cir.loadConstraints();
console.log("n_constraints", cir.constraints.length);
});
it ("absorb 1 (testvector generated from go)", async () => {
const s = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"]);
const block = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "128"]);
const expectedOut = strsToBigInts(["8342348566319207042", "319359607942176202", "14410076088654599075", "15666111399434436772", "9558421567405313402", "3396178318116504023", "794353847439963108", "12717011319735989377", "3503398863218919239", "5517201702366862678", "15999361614129160496", "1325524015888689985", "11971708408118944333", "14874486179441062217", "12554876384974234666", "11129975558302206043", "11257826431949606534", "2740710607956478714", "15000019752453010167", "15593606854132419294", "2598425978562809333","8872504799797239246", "1212062965004664308", "5443427421087086722", "10946808592826700411"]);
const sIn = u64ArrayToBits(s);
const blockIn = bytesToBits(block);
const expectedOutBits = u64ArrayToBits(expectedOut);
const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true);
const stateOut = witness.slice(1, 1+(25*64));
const stateOutU64 = bitsToU64Array(stateOut);
// console.log(stateOutU64, expectedOut);
assert.deepEqual(stateOutU64, expectedOut);
});
it ("absorb 2 (testvector generated from go)", async () => {
const s = strsToBigInts(["8342348566319207042", "319359607942176202", "14410076088654599075", "15666111399434436772", "9558421567405313402", "3396178318116504023", "794353847439963108", "12717011319735989377", "3503398863218919239", "5517201702366862678", "15999361614129160496", "1325524015888689985", "11971708408118944333", "14874486179441062217", "12554876384974234666", "11129975558302206043", "11257826431949606534", "2740710607956478714", "15000019752453010167", "15593606854132419294", "2598425978562809333","8872504799797239246", "1212062965004664308", "5443427421087086722", "10946808592826700411"]);
const block = strsToBigInts(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28","29", "30", "31", "1", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0","0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "128"]);
const expectedOut = strsToBigInts(["8909243822027471379", "1111840847970088140", "12093072708540612559", "11255033638786021658", "2082116894939842214", "12821085060245261575", "6901785969834988344", "3182430130277914993", "2164708585929408975", "14402143231999718904", "16231444410553803968", "1850945423480060493", "12856855675247400303", "1137248620532111171", "7389129221921446308", "12932467982741614601", "1350606937385760406", "10983682292859713641", "10305595434820307765", "13958651111365489854", "17206620388135196198", "4238113785249530092", "7230868147643218103", "603011106238724524", "16480095441097880488"]);
const sIn = u64ArrayToBits(s);
const blockIn = bytesToBits(block);
const expectedOutBits = u64ArrayToBits(expectedOut);
const witness = await cir.calculateWitness({ "s": sIn, "block": blockIn }, true);
const stateOut = witness.slice(1, 1+(25*64));
const stateOutU64 = bitsToU64Array(stateOut);
// console.log(stateOutU64, expectedOut);
assert.deepEqual(stateOutU64, expectedOut);
});
});

Loading…
Cancel
Save