#ifndef SHA_256
#define SHA_256 1

/*

uint8 SHA256_not_fresh(uint8 digest, uint4 block){

#define A digest.s0
#define B digest.s1
#define C digest.s2
#define D digest.s3
#define E digest.s4
#define F digest.s5
#define G digest.s6
#define H digest.s7
	RND(A,B,C,D,E,F,G,H, block.s0 + K[0]);
	RND(H,A,B,C,D,E,F,G, block.s1 + K[1]);
	RND(G,H,A,B,C,D,E,F, block.s2 + K[2]);
	RND(F,G,H,A,B,C,D,E, block.s3 + K[3]);
#undef A
#undef B
#undef C
#undef D
#undef E
#undef F
#undef G
#undef H

	return digest;
}
*/


/*
uint8 SHA256_fresh(uint4 block){

#define A block.s3
#define B block.s2
#define C block.s1
#define D block.s0
uint E;
uint F;
uint G = 0x98c7e2a2U;
uint H = 0xfc08884dU;

	H += D;
	D += G;
	C += Tr1(D) + Ch(D, FreshK.s4, FreshK.s5) + FreshK.s8;
	G = C + FreshK.s9 + Tr2(H) + Ch(H, FreshK.sa, FreshK.sb);
	B += Tr1(C) + Ch(C,D, FreshK.s4) + FreshK.sc;
	F = B + Tr2(G) + Maj(G,H, FreshK.s0) + FreshK.sd;
	A += Tr1(B) + Ch(B,C,D) + FreshK.se;
	E = A + Tr2(F) + Maj(F,G,H) + FreshK.sf;


	return (uint8)(A, B, C, D, E, F, G, H);
*/

/*
uint8 SHA256_fresh(uint4 block){


#define B00 block.s0
#define B01 block.s1
#define B02 block.s2
#define B03 block.s3

uint A = B03 + 0xa4ce148bU;
uint B = B02 + 0x0c2e12e0U;
uint C = B01 + 0xcd2a11aeU;
uint D = B00 + 0x98c7e2a2U;
uint E = 0x95F61999U;
uint F = 0x4498517BU;
uint G = 0xC3910C8EU;
uint H = B00 + 0xfc08884dU;

C += Tr1(D) + Ch(D, 0x510e527fU, 0x9b05688cU);
G += C + Tr2(H) + Ch(H, 0xfb6feee7U, 0x2a01a605U);

B += Tr1(C) + Ch(C,D, 0x510e527fU);
F += B + Tr2(G) + Maj(G,H, 0x6a09e667U);

A += Tr1(B) + Ch(B,C,D);
E += A + Tr2(F) + Maj(F,G,H);

#undef B00
#undef B01
#undef B02
#undef B03

return (uint8)(A, B, C, D, E, F, G, H);
}
*/




void SHA256(uint8 *digest, uint8 *block0, uint8 *block1, bool notfresh){
//uint8 SHA256(uint8 digest, uint8 block0, uint8 block1, bool notfresh){

	uint A, B, C, D, E, F, G, H;

	uint B00 = (*block0).s0;
	uint B01 = (*block0).s1;
	uint B02 = (*block0).s2;
	uint B03 = (*block0).s3;
/*
	uint B04 = (*block0).s4;
	uint B05 = (*block0).s5;
	uint B06 = (*block0).s6;
	uint B07 = (*block0).s7;

	uint B08 = (*block1).s0;
	uint B09 = (*block1).s1;
	uint B10 = (*block1).s2;
	uint B11 = (*block1).s3;
	uint B12 = (*block1).s4;
	uint B13 = (*block1).s5;
	uint B14 = (*block1).s6;
	uint B15 = (*block1).s7;
*/

	if(notfresh){
//digest = SHA256_not_fresh(digest, block0.lo);
		A = (*digest).s0;
		B = (*digest).s1;
		C = (*digest).s2;
		D = (*digest).s3;
		E = (*digest).s4;
		F = (*digest).s5;
		G = (*digest).s6;
		H = (*digest).s7;
		RND(A,B,C,D,E,F,G,H, B00 + K00);
		RND(H,A,B,C,D,E,F,G, B01 + K01);
		RND(G,H,A,B,C,D,E,F, B02 + K02);
		RND(F,G,H,A,B,C,D,E, B03 + K03);
	}else{
/*
digest = SHA256_fresh(block0.lo);
A = digest.s0;
B = digest.s1;
C = digest.s2;
D = digest.s3;
E = digest.s4;
F = digest.s5;
G = digest.s6;
H = digest.s7;
*/

//		G = 0x98c7e2a2U;
//		D = B00;

//digest = freshk.lo
//__constant uint16 FreshK = {0x6a09e667U, 0xBB67AE85U, 0x3C6EF372U, 0xA54FF53AU, 0x510e527fU, 0x9b05688cU, 0x1F83D9ABU, 0x5BE0CD19U,
//                            0xcd2a11aeU, 0xC3910C8EU, 0xfb6feee7U, 0x2a01a605U, 0x0c2e12e0U, 0x4498517BU, 0xa4ce148bU, 0x95F61999U};


/*
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19

*/

/*
		H = B00 + 0xfc08884dU;
		D = B00 + 0x98c7e2a2U;
		C = B01 + 0xcd2a11aeU;
		B = B02 + 0x0c2e12e0U;
		A = B03 + 0xa4ce148bU;

		C += Tr1(D) + Ch(D, digest.s4, digest.s5);

		G = C + 0xC3910C8EU;

		G += Tr2(H) + Ch(H, 0xfb6feee7U, 0x2a01a605U);
		//B = B02 + 0x0c2e12e0U;
		B += Tr1(C) + Ch(C,D, digest.s4);

		F = B + 0x4498517BU;

		F += Tr2(G) + Maj(G,H, digest.s0);
		//A = B03 + 0xa4ce148bU;
		A += Tr1(B) + Ch(B,C,D);

		E = A + 0x95F61999U;

		E += Tr2(F) + Maj(F,G,H);
*/

A = B03 + 0xa4ce148bU;
B = B02 + 0x0c2e12e0U;
C = B01 + 0xcd2a11aeU;
D = B00 + 0x98c7e2a2U;
E = 0x95F61999U;
F = 0x4498517BU;
G = 0xC3910C8EU;
H = B00 + 0xfc08884dU;

C += Tr1(D) + Ch(D, 0x510e527fU, 0x9b05688cU);
G += C + Tr2(H) + Ch(H, 0xfb6feee7U, 0x2a01a605U);
B += Tr1(C) + Ch(C,D, 0x510e527fU);
F += B + Tr2(G) + Maj(G,H, 0x6a09e667U);
A += Tr1(B) + Ch(B,C,D);
E += A + Tr2(F) + Maj(F,G,H);




//RND(A,B,C,D,E,F,G,H, B00 + K00);
//A = 
//B = 
//C = 
//D = 
//E = 
//F = digest.s4
//G = digest.s5
//H = 

//H += Tr1(E) + Ch(E, F, G);
//H += 0xC3910C8EU;
//G += Tr2(H) + Ch(H, 0xfb6feee7U, 0x2a01a605U);

/*
        A = digest.s0;
        B = 0xC3910C8EU;
        C = 0xfb6feee7U;
        D = 0x2a01a605U;
        E = digest.s4;
        F = digest.s5;
        G = 0x4498517BU;
        H = 0x95F61999U;


		RND(A,B,C,D,E,F,G,H, B00 + 0xfc08884dU);
        RND(H,A,B,C,D,E,F,G, B01 + 0xcd2a11aeU);
        RND(G,H,A,B,C,D,E,F, B02 + 0x0c2e12e0U);
        RND(F,G,H,A,B,C,D,E, B03 + 0xa4ce148bU);

*/
	}
/*
    uint K0 = K[4];
    uint K1 = K[5];
    uint K2 = K[6];
    uint K3 = K[7];
*/



    uint B04 = (*block0).s4;
    uint B05 = (*block0).s5;
    uint B06 = (*block0).s6;
    uint B07 = (*block0).s7;

    uint B08 = (*block1).s0;
    uint B09 = (*block1).s1;
    uint B10 = (*block1).s2;
    uint B11 = (*block1).s3;
    uint B12 = (*block1).s4;
    uint B13 = (*block1).s5;
    uint B14 = (*block1).s6;
    uint B15 = (*block1).s7;




	RND(E,F,G,H,A,B,C,D, B04 + K04);
	RND(D,E,F,G,H,A,B,C, B05 + K05);
	RND(C,D,E,F,G,H,A,B, B06 + K06);
	RND(B,C,D,E,F,G,H,A, B07 + K07);

/*
	uint K4 = K[8];
	uint K5 = K[9];
	uint K6 = K[10];
	uint K7 = K[11];
	K0 = K[12];
	K1 = K[13];
	K2 = K[14];
	K3 = K[15];
*/

	RND(A,B,C,D,E,F,G,H, B08 + K08);
	RND(H,A,B,C,D,E,F,G, B09 + K09);
	RND(G,H,A,B,C,D,E,F, B10 + K10);
	RND(F,G,H,A,B,C,D,E, B11 + K11);

	RND(E,F,G,H,A,B,C,D, B12 + K12);
	RND(D,E,F,G,H,A,B,C, B13 + K13);
	RND(C,D,E,F,G,H,A,B, B14 + K14);
	RND(B,C,D,E,F,G,H,A, B15 + K15);

/*
	K0 = K[16];
	K1 = K[17];
	K2 = K[18];
	K3 = K[19];
	K4 = K[20];
	K5 = K[21];
	K6 = K[22];
	K7 = K[23];
*/

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K16);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K17);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K18);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K19);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K20);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K21);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K22);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K23);

/*
	K0 = K[24];
	K1 = K[25];
	K2 = K[26];
	K3 = K[27];
	K4 = K[28];
	K5 = K[29];
	K6 = K[30];
	K7 = K[31];
*/

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K24);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K25);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K26);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K27);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K28);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K29);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K30);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K31);

/*
	K0 = K[32];
	K1 = K[33];
	K2 = K[34];
	K3 = K[35];
	K4 = K[36];
	K5 = K[37];
	K6 = K[38];
	K7 = K[39];
*/

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K32);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K33);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K34);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K35);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K36);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K37);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K38);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K39);

/*
	K0 = K[40];
	K1 = K[41];
	K2 = K[42];
	K3 = K[43];
	K4 = K[44];
	K5 = K[45];
	K6 = K[46];
	K7 = K[47];
*/

	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K40);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K41);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K42);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K43);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K44);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K45);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K46);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K47);

/*
	K0 = K[48];
	K1 = K[49];
	K2 = K[50];
	K3 = K[51];
	K4 = K[52];
	K5 = K[53];
	K6 = K[54];
	K7 = K[55];
*/

	B00 += Wr1(B14) + B09 + Wr2(B01);
	RND(A,B,C,D,E,F,G,H, B00 + K48);
	B01 += Wr1(B15) + B10 + Wr2(B02);
	RND(H,A,B,C,D,E,F,G, B01 + K49);
	B02 += Wr1(B00) + B11 + Wr2(B03);
	RND(G,H,A,B,C,D,E,F, B02 + K50);
	B03 += Wr1(B01) + B12 + Wr2(B04);
	RND(F,G,H,A,B,C,D,E, B03 + K51);

	B04 += Wr1(B02) + B13 + Wr2(B05);
	RND(E,F,G,H,A,B,C,D, B04 + K52);
	B05 += Wr1(B03) + B14 + Wr2(B06);
	RND(D,E,F,G,H,A,B,C, B05 + K53);
	B06 += Wr1(B04) + B15 + Wr2(B07);
	RND(C,D,E,F,G,H,A,B, B06 + K54);
	B07 += Wr1(B05) + B00 + Wr2(B08);
	RND(B,C,D,E,F,G,H,A, B07 + K55);

/*
	K0 = K[56];
	K1 = K[57];
	K2 = K[58];
	K3 = K[59];
	K4 = K[60];
	K5 = K[61];
	K6 = K[62];
	K7 = K[63];
*/
	B08 += Wr1(B06) + B01 + Wr2(B09);
	RND(A,B,C,D,E,F,G,H, B08 + K56);
	B09 += Wr1(B07) + B02 + Wr2(B10);
	RND(H,A,B,C,D,E,F,G, B09 + K57);
	B10 += Wr1(B08) + B03 + Wr2(B11);
	RND(G,H,A,B,C,D,E,F, B10 + K58);
	B11 += Wr1(B09) + B04 + Wr2(B12);
	RND(F,G,H,A,B,C,D,E, B11 + K59);

	B12 += Wr1(B10) + B05 + Wr2(B13);
	RND(E,F,G,H,A,B,C,D, B12 + K60);
	B13 += Wr1(B11) + B06 + Wr2(B14);
	RND(D,E,F,G,H,A,B,C, B13 + K61);
	B14 += Wr1(B12) + B07 + Wr2(B15);
	RND(C,D,E,F,G,H,A,B, B14 + K62);
	B15 += Wr1(B13) + B08 + Wr2(B00);
	RND(B,C,D,E,F,G,H,A, B15 + K63);

/*
	A += T0x;
	B += T0y;
	C += T0z;
	D += T0w;
	E += T1x;
	F += T1y;
	G += T1z;
	H += T1w;
*/

//T += (uint8)(A, B, C, D, E, F, G, H);
//data[(idx.s0)] = T;
/*
data[(idx.s0)].s0 = A;
data[(idx.s0)].s1 = B;
data[(idx.s0)].s2 = C;
data[(idx.s0)].s3 = D;
data[(idx.s0)].s4 = E;
data[(idx.s0)].s5 = F;
data[(idx.s0)].s6 = G;
data[(idx.s0)].s7 = H;
data[(idx.s0)] += T;
*/
//return(T);

//*digest += (uint8)(A, B, C, D, E, F, G, H);

(*digest).s0 += A;
(*digest).s1 += B;
(*digest).s2 += C;
(*digest).s3 += D;
(*digest).s4 += E;
(*digest).s5 += F;
(*digest).s6 += G;
(*digest).s7 += H;

//return digest;
//return (uint8)(A, B, C, D, E, F, G, H);
}

/*
void SHA256_fixed(uint8 *digest){

	uint A = (*digest).s0;
	uint B = (*digest).s1;
	uint C = (*digest).s2;
	uint D = (*digest).s3;
	uint E = (*digest).s4;
	uint F = (*digest).s5;
	uint G = (*digest).s6;
	uint H = (*digest).s7;

    for(uint i=0; i<8; i++){
        RND(A,B,C,D,E,F,G,H, fixedWa[i]);
        RND(H,A,B,C,D,E,F,G, fixedWb[i]);
        RND(G,H,A,B,C,D,E,F, fixedWc[i]);
        RND(F,G,H,A,B,C,D,E, fixedWd[i]);
        RND(E,F,G,H,A,B,C,D, fixedWe[i]);
        RND(D,E,F,G,H,A,B,C, fixedWf[i]);
        RND(C,D,E,F,G,H,A,B, fixedWg[i]);
        RND(B,C,D,E,F,G,H,A, fixedWh[i]);
    }

//	*digest += (uint8)(A, B, C, D, E, F, G, H);

(*digest).s0 += A;
(*digest).s1 += B;
(*digest).s2 += C;
(*digest).s3 += D;
(*digest).s4 += E;
(*digest).s5 += F;
(*digest).s6 += G;
(*digest).s7 += H;


}
*/

#endif