diff --git a/circuits/keccak256.circom b/circuits/keccak256.circom index 8c0daa7..51267a1 100644 --- a/circuits/keccak256.circom +++ b/circuits/keccak256.circom @@ -64,3 +64,34 @@ template KeccakfRound(r) { out[i] <== iota.out[i]; } } + +template Keccakf() { + signal input in[25*64]; + signal output out[25*64]; + var i; + var j; + + // 24 rounds + component round[24]; + signal midRound[24*25*64]; + for (i=0; i<24; i++) { + round[i] = KeccakfRound(i); + if (i==0) { + for (j=0; j<25*64; j++) { + midRound[j] <== in[j]; + } + } + for (j=0; j<25*64; j++) { + round[i].in[j] <== midRound[i*25*64+j]; + } + if (i<23) { + for (j=0; j<25*64; j++) { + midRound[(i+1)*25*64+j] <== round[i].out[j]; + } + } + } + + for (i=0; i<25*64; i++) { + out[i] <== round[23].out[i]; + } +} diff --git a/go-keccak256-bits-impl/keccak_test.go b/go-keccak256-bits-impl/keccak_test.go index 3e9c9bf..7605a7f 100644 --- a/go-keccak256-bits-impl/keccak_test.go +++ b/go-keccak256-bits-impl/keccak_test.go @@ -92,8 +92,19 @@ func TestKeccakf(t *testing.T) { 15083668107635345971}) // compute again keccakf on the current state - // s = keccakf(s) - // qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, []uint64{}) + s = keccakf(s) + qt.Assert(t, bitsToU64Array(s[:]), qt.DeepEquals, + []uint64{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}) } func TestFinal(t *testing.T) { diff --git a/test/circuits/keccakf_test.circom b/test/circuits/keccakf_test.circom new file mode 100644 index 0000000..f3ff679 --- /dev/null +++ b/test/circuits/keccakf_test.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../../circuits/keccak256.circom"; + +component main = Keccakf(); diff --git a/test/keccak256.js b/test/keccak256.js index 63d4038..0cdf122 100644 --- a/test/keccak256.js +++ b/test/keccak256.js @@ -300,7 +300,7 @@ describe("Keccak-Pad test", function () { }); }); -describe("keccakf test", function () { +describe("keccakfRound test", function () { this.timeout(100000); // apt install nlohmann-json3-dev @@ -346,3 +346,47 @@ describe("keccakf test", function () { assert.deepEqual(stateOutU64, expectedOut); }); }); + +describe("keccakf test", function () { + this.timeout(100000); + + it ("keccakf 1 (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 = [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"]); + + const stateIn = u64ArrayToBits(input); + const expectedOutBits = u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); + + 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"]); + + const stateIn = u64ArrayToBits(input); + const expectedOutBits = u64ArrayToBits(expectedOut); + + const witness = await cir.calculateWitness({ "in": stateIn }, true); + + const stateOut = witness.slice(1, 1+(25*64)); + const stateOutU64 = bitsToU64Array(stateOut); + // console.log(stateOutU64, expectedOut); + assert.deepEqual(stateOutU64, expectedOut); + }); +});