From 275ae7820a39aac6b721701c738f41a8fc48baa6 Mon Sep 17 00:00:00 2001 From: rickb80 Date: Tue, 21 Nov 2023 12:13:22 +0100 Subject: [PATCH 1/3] Added SHA256F --- tools/sm/sha256/sha256.cpp | 193 ++++++++++++++++++------------------- tools/sm/sha256/sha256.hpp | 1 + 2 files changed, 93 insertions(+), 101 deletions(-) diff --git a/tools/sm/sha256/sha256.cpp b/tools/sm/sha256/sha256.cpp index 578b0d860..8d38b8c85 100644 --- a/tools/sm/sha256/sha256.cpp +++ b/tools/sm/sha256/sha256.cpp @@ -4,6 +4,22 @@ #include "timer.hpp" #include "sha256.hpp" +// Initialize hash values: +// (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19) +const uint32_t hIn[8] = {0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19}; + +// Initialize array of round constants: +// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): +const uint32_t k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; + void SHA256String (const string &s, string &hash) { string ba; @@ -20,29 +36,6 @@ void SHA256 (const uint8_t * pData, uint64_t dataSize, string &hash) void SHA256 (const uint8_t * pData, uint64_t dataSize, mpz_class &hashScalar) { - // Initialize hash values: - // (first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19): - uint32_t h0 = 0x6a09e667; - uint32_t h1 = 0xbb67ae85; - uint32_t h2 = 0x3c6ef372; - uint32_t h3 = 0xa54ff53a; - uint32_t h4 = 0x510e527f; - uint32_t h5 = 0x9b05688c; - uint32_t h6 = 0x1f83d9ab; - uint32_t h7 = 0x5be0cd19; - - // Initialize array of round constants: - // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311): - uint32_t k[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; - // Padding: // original message of length L bits // padded message: 1 bit @@ -64,15 +57,12 @@ void SHA256 (const uint8_t * pData, uint64_t dataSize, mpz_class &hashScalar) { padding[i] = pData[dataPosition+i]; } + uint32_t stIn[8]; + memcpy(stIn, hIn, sizeof(hIn)); // Process the message in successive 512-bit chunks: break message into 512-bit chunks for (uint64_t chunk=0; chunk Date: Tue, 21 Nov 2023 12:15:18 +0100 Subject: [PATCH 2/3] Avoid Warning --- src/sm/padding_sha256/padding_sha256_executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sm/padding_sha256/padding_sha256_executor.cpp b/src/sm/padding_sha256/padding_sha256_executor.cpp index 293647f89..f065b6bb7 100644 --- a/src/sm/padding_sha256/padding_sha256_executor.cpp +++ b/src/sm/padding_sha256/padding_sha256_executor.cpp @@ -104,7 +104,7 @@ void PaddingSha256Executor::execute (vector &input, uint64_t s=input[i].dataBytes.size()-1-j; if(s < 8) pols.lengthSection[p] = fr.one(); - if(s < 4) pols.accLength[p] = fr.fromU64((input[i].realLen*8)&&(0xFFFFFFFF<<(s*8))); //rick: ?? + if(s < 4) pols.accLength[p] = fr.fromU64((input[i].realLen<<3)&&(0xFFFFFFFF<<(s*8))); //check bool lastBlock = (p % bytesPerBlock) == (bytesPerBlock - 1); bool lastHash = lastBlock && ((!fr.isZero(pols.spare[p])) || fr.isZero(pols.rem[p])); From eef33303a5cdfdb452b7ec386a6f8ccbd17f58f1 Mon Sep 17 00:00:00 2001 From: rickb80 Date: Tue, 21 Nov 2023 15:04:44 +0100 Subject: [PATCH 3/3] Add PaddingSha256BitExecutor --- .../padding_sha256bit_executor.cpp | 189 ++++++++---------- .../padding_sha256bit_executor.hpp | 13 +- 2 files changed, 90 insertions(+), 112 deletions(-) diff --git a/src/sm/padding_sha256bit/padding_sha256bit_executor.cpp b/src/sm/padding_sha256bit/padding_sha256bit_executor.cpp index 0356221a2..eaf5dc2af 100644 --- a/src/sm/padding_sha256bit/padding_sha256bit_executor.cpp +++ b/src/sm/padding_sha256bit/padding_sha256bit_executor.cpp @@ -2,165 +2,142 @@ #include "sha256.hpp" #include "timer.hpp" #include "definitions.hpp" -#include "Keccak-more-compact.hpp" #include "zkmax.hpp" #include "zklog.hpp" -inline uint64_t getStateBit ( const uint8_t (&state)[200], uint64_t i ) -{ - return (state[i/8] >> (i%8)) & 1; -} +const uint32_t hIn[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; -inline void setStateBit (uint8_t (&state)[200], uint64_t i, uint64_t b ) +inline uint64_t getStateBit ( const uint32_t (&state)[8], uint64_t i ) { - state[i/8] ^= (b << (i%8)); -} - -inline void callKeccakF (const uint8_t (&inputState)[200], uint8_t (&outputState)[200]) -{ - /* Copy inputState into OuputState */ - memcpy(outputState, inputState, sizeof(outputState)); - - /* Call keccak-f (one single round) to update outputState */ - KeccakF1600(outputState); + uint64_t sh = 31 - (i%32); + return (state[i/32] >> sh) & 1; } void PaddingSha256BitExecutor::execute (vector &input, PaddingSha256BitCommitPols &pols, vector &required) { - #if 0 -#ifdef LOG_TIME_STATISTICS - struct timeval t; - uint64_t keccakTime=0, keccakTimes=0; -#endif + // Check that input size does not exeed the number of slots if (input.size() > nSlots) { zklog.error("PaddingKKBitExecutor::execute() Too many entries input.size()=" + to_string(input.size()) + " > nSlots=" + to_string(nSlots)); exitProcess(); } - - uint64_t curInput = 0; uint64_t p = 0; - uint64_t pDone = 0; - // Convert pols.sOutX to and array, for programming convenience CommitPol sOut[8] = { pols.sOut0, pols.sOut1, pols.sOut2, pols.sOut3, pols.sOut4, pols.sOut5, pols.sOut6, pols.sOut7 }; - uint8_t currentState[200]; - bool bCurStateWritten = false; + uint8_t zeroIn[64]; + zeroIn[0] = 0x80; + memset(&zeroIn[1], 0, sizeof(zeroIn)-1); + + uint32_t zeroOut[8]; + SHA256F(zeroIn,hIn,zeroOut); + + uint32_t currentState[8]; //rich: check + currentState[0] = 0x80; + memset(¤tState[0], 0, sizeof(currentState)-1); + for (uint64_t i=0; i=input.size()) || (input[curInput].connected == false)) + // optimize avoiding copies + if ((i>=input.size()) || (input[i].connected == false)) { connected = false; - memset(stateWithR, 0, sizeof(stateWithR)); + memcpy(stIn, hIn, sizeof(hIn)); } else { - // Copy: stateWithR = currentState; - memcpy(&stateWithR, ¤tState, sizeof(stateWithR)); + memcpy(&stIn, ¤tState, sizeof(currentState)); } - for (uint64_t j=0; j<136; j++) + if(i >= input.size()) { - uint8_t byte = (curInput < input.size()) ? input[curInput].data[j] : 0; - pols.r8[p] = fr.zero(); - for (uint64_t k=0; k<8; k++) - { - uint64_t bit = (byte >> k) & 1; - setStateBit(stateWithR, j*8+k, bit); - pols.rBit[p] = fr.fromU64(bit); - pols.r8[p+1] = fr.fromU64( fr.toU64(pols.r8[p]) | ((uint64_t(bit) << k)) ); - if (bCurStateWritten) pols.sOutBit[p] = fr.fromU64( getStateBit(currentState, j*8 + k) ); - if (connected) pols.connected[p] = fr.one(); - p++; - } - - if (connected) pols.connected[p] = fr.one(); - p++; + memcpy(inR, zeroIn, sizeof(zeroIn)); + memcpy(stOut, zeroOut, sizeof(zeroOut)); } - - for (uint64_t j=0; j<512; j++) + else { - if (bCurStateWritten) pols.sOutBit[p] = fr.fromU64( getStateBit(currentState, 136*8 + j) ); - if (connected) pols.connected[p] = fr.one(); - p++; + memcpy(inR, input[i].data, sizeof(inR)); + SHA256F(inR, stIn, stOut); } -#ifdef LOG_TIME_STATISTICS - gettimeofday(&t, NULL); -#endif - callKeccakF(stateWithR, currentState); - bCurStateWritten = true; -#ifdef LOG_TIME_STATISTICS - keccakTime += TimeDiff(t); - keccakTimes+=1; -#endif - Bits2FieldExecutorInput bits2FieldExecutorInput; - // Copy: bits2FieldExecutorInput.inputState = stateWithR - memcpy(&bits2FieldExecutorInput.inputState, stateWithR, sizeof(bits2FieldExecutorInput.inputState)); - // Copy: bits2FieldExecutorInput.outputState = currentState - memcpy(&bits2FieldExecutorInput.outputState, currentState, sizeof(bits2FieldExecutorInput.outputState)); - - required.push_back(bits2FieldExecutorInput); for (uint64_t j=0; j<256; j++) { - pols.sOutBit[p] = fr.fromU64( getStateBit(currentState, j) ); - if (connected) pols.connected[p] = fr.one(); - - uint64_t bit = j%8; - uint64_t byte = j/8; - uint64_t chunk = 7 - byte/4; - uint64_t byteInChunk = 3 - byte%4; - - for (uint64_t k=0; k<8; k++) - { - if ( k == chunk) { - sOut[k][p+1] = fr.fromU64( fr.toU64(sOut[k][p]) | (fr.toU64(pols.sOutBit[p]) << ( byteInChunk*8 + bit)) ); - } else { - sOut[k][p+1] = sOut[k][p]; + pols.s1[p] = fr.fromU64(getStateBit(currentState, j)); + if(connected){ + pols.connected[p] = fr.one(); + pols.s2[p] = pols.s1[p]; + }else{ + pols.s2[p] = fr.fromU64(getStateBit(hIn, j)); + } + p++; + } + for(uint64_t j=0; j < 512; ++j){ + + uint64_t byteIdx = j / 8; + uint64_t bitIdx = 7 - (j % 8); + uint64_t byte = (i < input.size()) ? input[i].data[byteIdx] : 0; + uint64_t bit = (byte >> bitIdx) & 1; + + if(connected) pols.connected[p] = fr.one(); + pols.s1[p] = fr.fromU64(bit); + pols.s2[p] = fr.fromU64(getStateBit(stOut, j)); + + uint64_t k = 7 - (j % 8); + uint64_t inc = fr.toU64(pols.s1[p]) << k; + pols.r8[p] = (k==7) ? fr.fromU64(inc) : fr.add(pols.r8[p-1], fr.fromU64(inc)); + + for(uint64_t r=0; r < 8; r++){ + if(j>0){ + sOut[r][p] = sOut[r][p-1]; } } + + uint64_t inc2 = fr.toU64(pols.s2[p]) << (31-(j%32)); + + if( j< 32){ + sOut[0][p] = fr.add(sOut[0][p], fr.fromU64(inc2)); + } else if (j<64){ + sOut[1][p] = fr.add(sOut[1][p], fr.fromU64(inc2)); + } else if (j<96){ + sOut[2][p] = fr.add(sOut[2][p], fr.fromU64(inc2)); + } else if (j<128){ + sOut[3][p] = fr.add(sOut[3][p], fr.fromU64(inc2)); + } else if (j<160){ + sOut[4][p] = fr.add(sOut[4][p], fr.fromU64(inc2)); + } else if (j<192){ + sOut[5][p] = fr.add(sOut[5][p], fr.fromU64(inc2)); + } else if (j<224){ + sOut[6][p] = fr.add(sOut[6][p], fr.fromU64(inc2)); + } else if (j<256){ + sOut[7][p] = fr.add(sOut[7][p], fr.fromU64(inc2)); + } p += 1; } + //required.Bits2FieldSha256.push([stateWithR, curState]); //rick: pending - if (connected) pols.connected[p] = fr.one(); - p++; - - curInput++; + memcpy(currentState, stOut, sizeof(currentState)); } - pDone = p; - // Connect the last state with the first uint64_t pp = 0; - for (uint64_t j=0; j<136; j++) + for (uint64_t j=0; j<256; j++) { - for (uint64_t k=0; k<8; k++) - { - pols.sOutBit[pp] = fr.fromU64( getStateBit(currentState, j*8 + k) ); - pp += 1; - } - pols.sOutBit[pp] = fr.zero(); + pols.s1[pp] = fr.fromU64( getStateBit(currentState, j)); pp++; } - for (uint64_t j=0; j<512; j++) - { - pols.sOutBit[pp] = fr.fromU64( getStateBit(currentState, 136*8 + j) ); - pp++; - } + uint64_t pDone = p; zklog.info("PaddingKKBitExecutor successfully processed " + to_string(input.size()) + " Keccak actions p=" + to_string(p) + " pDone=" + to_string(pDone) + " (" + to_string((double(pDone)*100)/N) + "%)"); -#ifdef LOG_TIME_STATISTICS - zklog.info("TIMER STATISTICS: PaddingKKBitExecutor: Keccak time: " + to_string(double(keccakTime)/1000) + " ms, called " + to_string(keccakTimes) + " times, so " + to_string(keccakTime/zkmax(keccakTimes,(uint64_t)1)) + " us/time"); -#endif -#endif + } diff --git a/src/sm/padding_sha256bit/padding_sha256bit_executor.hpp b/src/sm/padding_sha256bit/padding_sha256bit_executor.hpp index 12cf442e6..33ab03f4b 100644 --- a/src/sm/padding_sha256bit/padding_sha256bit_executor.hpp +++ b/src/sm/padding_sha256bit/padding_sha256bit_executor.hpp @@ -4,7 +4,6 @@ #include #include "definitions.hpp" #include "sm/pols_generated/commit_pols.hpp" -#include "sm/bits2field/bits2field_executor.hpp" #include "sm/bits2field_sha256/bits2field_sha256_executor.hpp" USING_PROVER_FORK_NAMESPACE; @@ -15,12 +14,12 @@ class PaddingSha256BitExecutorInput { public: - /* If connected, this means that this is not the first block of a keccak message to hash, + /* If connected, this means that this is not the first block of the sha256 message to hash, and then the state of the previous block is used as initial state of this block */ bool connected; - /* Input keccak block data: 136 bytes = 1088 bits */ - uint8_t data[136]; + /* Input sha256 block data: 64 bytes = 512 bits */ + uint8_t data[64]; /* Constructor */ PaddingSha256BitExecutorInput() : connected(false) {}; @@ -36,6 +35,7 @@ class PaddingSha256BitExecutor /* Constant values */ const uint64_t N; const uint64_t slotSize; + const uint64_t bitsPerElement; const uint64_t nSlots; public: @@ -44,8 +44,9 @@ class PaddingSha256BitExecutor PaddingSha256BitExecutor(Goldilocks &fr) : fr(fr), N(PROVER_FORK_NAMESPACE::PaddingSha256BitCommitPols::pilDegree()), - slotSize(155286), - nSlots(44*((N-1)/slotSize)) {}; + slotSize(31487), + bitsPerElement(6), + nSlots(bitsPerElement*((N-1)/slotSize)) {}; /* Executor */ void execute (vector &input, PROVER_FORK_NAMESPACE::PaddingSha256BitCommitPols &pols, vector &required);