diff --git a/circuits/iota.circom b/circuits/iota.circom new file mode 100644 index 0000000..4f40da2 --- /dev/null +++ b/circuits/iota.circom @@ -0,0 +1,41 @@ +pragma circom 2.0.0; + +include "./utils.circom"; + +template RC(r) { + signal output out[64]; + var rc[24] = [ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, + 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, + 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 + ]; + for (var i=0; i<64; i++) { + out[i] <== (rc[r] >> i) & 1; + } +} + +template Iota(r) { + signal input in[25*64]; + signal output out[25*64]; + var i; + + component rc = RC(r); + + component iota = XorArray(64); + for (var i=0; i<64; i++) { + iota.a[i] <== in[i]; + iota.b[i] <== rc.out[i]; + } + for (i=0; i<64; i++) { + out[i] <== iota.out[i]; + } + for (i=64; i<25*64; i++) { + out[i] <== in[i]; + } +} + diff --git a/test/circuits/iota10_test.circom b/test/circuits/iota10_test.circom new file mode 100644 index 0000000..8b4f5e2 --- /dev/null +++ b/test/circuits/iota10_test.circom @@ -0,0 +1,6 @@ +pragma circom 2.0.0; + +include "../../circuits/iota.circom"; + +component main = Iota(10); + diff --git a/test/circuits/iota3_test.circom b/test/circuits/iota3_test.circom new file mode 100644 index 0000000..1a747d2 --- /dev/null +++ b/test/circuits/iota3_test.circom @@ -0,0 +1,6 @@ +pragma circom 2.0.0; + +include "../../circuits/iota.circom"; + +component main = Iota(3); + diff --git a/test/keccak256.js b/test/keccak256.js index 352a51d..dfcb9c4 100644 --- a/test/keccak256.js +++ b/test/keccak256.js @@ -183,3 +183,38 @@ describe("Chi test", function () { assert.deepEqual(stateOutU64, expectedOut); }); }); + +describe("Iota test", function () { + this.timeout(100000); + + it ("Iota 3 (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "iota3_test.circom")); + + 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 = [9223372039002292224,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 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 ("Iota 10 (testvector generated from go)", async () => { + const cir = await wasm_tester(path.join(__dirname, "circuits", "iota10_test.circom")); + + const input = [9223372039002292224,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 = [9223372036854775817,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 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); + }); +});