Skip to content

Commit

Permalink
Merge pull request #722 from 0xPolygonHermez/fork_7_SMSHA256
Browse files Browse the repository at this point in the history
Add PaddingSha256BitExecutor
  • Loading branch information
rickb80 authored Nov 21, 2023
2 parents 3c73ff3 + 099b867 commit 75c78e9
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 214 deletions.
2 changes: 1 addition & 1 deletion src/sm/padding_sha256/padding_sha256_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void PaddingSha256Executor::execute (vector<PaddingSha256ExecutorInput> &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]));
Expand Down
189 changes: 83 additions & 106 deletions src/sm/padding_sha256bit/padding_sha256bit_executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<PaddingSha256BitExecutorInput> &input, PaddingSha256BitCommitPols &pols, vector<Bits2FieldSha256ExecutorInput> &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(&currentState[0], 0, sizeof(currentState)-1);


for (uint64_t i=0; i<nSlots; i++)
{
bool connected = true;

uint8_t stateWithR[200];
bool connected = true;
uint32_t stIn[8];
uint32_t stOut[8];
uint8_t inR[64];

// If this is the first block of a message, or we run out of them, start from a reset state
if ((curInput>=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, &currentState, sizeof(stateWithR));
memcpy(&stIn, &currentState, 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

}

13 changes: 7 additions & 6 deletions src/sm/padding_sha256bit/padding_sha256bit_executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <vector>
#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;
Expand All @@ -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) {};
Expand All @@ -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:
Expand All @@ -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<PaddingSha256BitExecutorInput> &input, PROVER_FORK_NAMESPACE::PaddingSha256BitCommitPols &pols, vector<Bits2FieldSha256ExecutorInput> &required);
Expand Down
Loading

0 comments on commit 75c78e9

Please sign in to comment.