/****************************************************************************** * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ // based on SaM code by Come-from-Beyond #ifdef DEFINES_ONLY #ifndef crypto777_SaM_h #define crypto777_SaM_h #include #include #include #define TRIT signed char #define TRIT_FALSE 1 #define TRIT_UNKNOWN 0 #define TRIT_TRUE -1 #define SAM_HASH_SIZE 243 #define SAM_STATE_SIZE (SAM_HASH_SIZE * 3) #define SAM_NUMBER_OF_ROUNDS 9 #define SAM_DELTA 254 #define SAMHIT_LIMIT ((uint64_t)1594323 * 4782969) //7625597484987LL // 3 ** 27 #define MAX_CRYPTO777_HIT (((uint64_t)1 << 62) / 1000) //#include "bits777.c" //#include "utils777.c" #include #include "../includes/curve25519.h" #define MAX_INPUT_SIZE ((int32_t)(65536 - sizeof(bits256) - 2*sizeof(uint32_t))) struct SaM_info { bits384 bits; TRIT trits[SAM_STATE_SIZE],hash[SAM_HASH_SIZE]; }; struct SaMhdr { bits384 sig; uint32_t timestamp,nonce; uint8_t numrounds,leverage; }; void SaM_Initialize(struct SaM_info *state); int32_t SaM_Absorb(struct SaM_info *state,const uint8_t *input,uint32_t inputSize,const uint8_t *input2,uint32_t inputSize2); bits384 SaM_emit(struct SaM_info *state); bits384 SaM_encrypt(uint8_t *dest,uint8_t *src,int32_t len,bits384 password,uint32_t timestamp); uint64_t SaM_threshold(int32_t leverage); uint64_t SaM(bits384 *sigp,uint8_t *input,int32_t inputSize,uint8_t *input2,int32_t inputSize2); uint32_t SaM_nonce(void *data,int32_t datalen,int32_t leverage,int32_t maxmillis,uint32_t nonce); //uint64_t SaMnonce(bits384 *sigp,uint32_t *noncep,uint8_t *buf,int32_t len,uint64_t threshold,uint32_t rseed,int32_t maxmillis); #endif #else #ifndef crypto777_SaM_c #define crypto777_SaM_c #ifndef crypto777_SaM_h #define DEFINES_ONLY #include "SaM.c" #undef DEFINES_ONLY #endif static int32_t SAM_INDICES[SAM_STATE_SIZE]; void SaM_PrepareIndices() { int32_t i,nextIndex,currentIndex = 0; for (i=0; itrits[currentIndex],state->trits[nextIndex]); //rightPart.trits[i] = SaM_Bias(state->trits[nextIndex],state->trits[currentIndex]); leftPart.trits[i] = SAMBIAS[state->trits[currentIndex]+1][1+state->trits[nextIndex]]; rightPart.trits[i] = SAMBIAS[state->trits[nextIndex]+1][1+state->trits[currentIndex]]; currentIndex = nextIndex; } for (i=0; itrits[i] = SaM_Sum(leftPart.trits[currentIndex],rightPart.trits[nextIndex]); state->trits[i] = SAMSUM[leftPart.trits[currentIndex]+1][1+rightPart.trits[nextIndex]]; currentIndex = nextIndex; } } } void SaM_Initialize(struct SaM_info *state) { int32_t i; for (i=SAM_HASH_SIZE; itrits[i] = (i & 1) ? TRIT_FALSE : TRIT_TRUE; } void SaM_Squeeze(struct SaM_info *state,TRIT *output) { memcpy(output,state->trits,SAM_HASH_SIZE * sizeof(TRIT)); SaM_SplitAndMerge(state); } void _SaM_Absorb(struct SaM_info *state,const TRIT *input,const int32_t inputSize) { int32_t size,i,remainder = inputSize; do { size = remainder >= SAM_HASH_SIZE ? SAM_HASH_SIZE : remainder; memcpy(state->trits,&input[inputSize - remainder],size); remainder -= SAM_HASH_SIZE; if ( size < SAM_HASH_SIZE ) for (i=size; itrits[i] = (i & 1) ? TRIT_FALSE : TRIT_TRUE; SaM_SplitAndMerge(state); } while ( remainder > 0 ); } int32_t SaM_Absorb(struct SaM_info *state,const uint8_t *input,uint32_t inputSize,const uint8_t *input2,uint32_t inputSize2) { //TRIT output[(MAX_INPUT_SIZE + sizeof(struct SaMhdr)) << 3]; TRIT *trits,tritbuf[4096]; int32_t i,size,n = 0; /*if ( inputSize + inputSize2 > sizeof(output) ) { printf("SaM overflow (%d + %d) > %ld\n",inputSize,inputSize2,sizeof(output)); if ( inputSize > MAX_INPUT_SIZE ) inputSize = MAX_INPUT_SIZE; inputSize2 = 0; }*/ size = (inputSize + inputSize2) << 3; trits = (size < sizeof(tritbuf)) ? tritbuf : malloc(size); if ( input != 0 && inputSize != 0 ) { for (i=0; i<(inputSize << 3); i++) trits[n++] = ((input[i >> 3] & (1 << (i & 7))) != 0); } if ( input2 != 0 && inputSize2 != 0 ) { for (i=0; i<(inputSize2 << 3); i++) trits[n++] = ((input2[i >> 3] & (1 << (i & 7))) != 0); } _SaM_Absorb(state,trits,n); if ( trits != tritbuf ) free(trits); return(n); } static TRIT InputA[] = { 0 }; // zero len static TRIT OutputA[] = { 1, -1, 1, 1, -1, -1, 0, -1, 0, 0, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, 0, 0, 1, 1, -1, -1, 0, 0, 1, -1, -1, 0, 0, -1, 1, -1, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, 1, 0, 1, 0, -1, -1, -1, -1, 0, 1, -1, 1, -1, 0, 1, 1, 0, 0, -1, 0, 1, 1, -1, 1, 0, 0, 0, 1, 0, -1, 1, 1, 0, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 0, 1, -1, 1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 1, -1, 0, 0, 1, 1, 0, 0, -1, 1, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, 0, -1, 1, -1, 0, 1, -1, 0, -1, 1, 1, 1, -1, 0, 1, 1, -1, -1, 0, 0, 1, -1, -1, -1, 0, -1, -1, 1, 1, 0, 1, 0, 1, -1, 1, -1, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, -1, 1, -1, 0, 0, 1, 0, -1, -1, -1, 1, -1, 1, -1, -1, 1, 0, 1, -1, 1, -1, 1, -1, 1, 0, 1, 0, 1, -1, -1, -1, -1, 1, 0, 0, -1, -1, 1, 0, 1, 1, -1, 1, -1, -1, -1, 0, 0, -1, 0, 1, 1, 1, 0, 1, 1, -1, 1, 1, 0, 1, 1, 1, 0, -1, 0, 0, -1, -1, -1 }; static TRIT InputB[] = { 0 }; static TRIT OutputB[] = { -1, -1, -1, 1, 0, 0, 1, 1, 0, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 1, 0, -1, 1, 0, 1, 0, 1, -1, 0, -1, 0, 0, -1, 1, -1, -1, 0, 0, 1, -1, -1, 0, 0, -1, 1, 1, 0, 1, 0, 0, 1, -1, 1, 0, -1, -1, 1, -1, 0, -1, 1, -1, 0, 0, 0, 1, -1, 0, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 0, 1, -1, -1, -1, 0, 1, 0, 0, -1, 1, 1, 0, 0, -1, 1, 1, 0, -1, -1, 0, 0, 0, -1, 1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 1, 0, -1, 1, 1, -1, 1, 0, 1, -1, -1, 1, 1, 0, -1, 0, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 0, 0, 0, 0, -1, -1, 1, 1, 1, -1, 1, 0, -1, 1, 0, 1, 0, 0, -1, -1, 1, 1, 0, 0, 1, 0, 0, 0, 0, -1, 1, 0, 0, 1, 1, 0, -1, 1, -1, 1, 0, -1, 0, 0, 1, -1, -1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, -1, 1, 1, 1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 0, -1, 1, 1, -1, 0, -1, 1, 1, 0, -1, -1, -1, -1, 1, 0, 0, -1, -1, -1, 0, 1 }; static TRIT InputC[] = { 1 }; static TRIT OutputC[] = { 1, -1, 1, 1, -1, -1, 0, -1, 0, 0, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, 0, 0, 1, 1, -1, -1, 0, 0, 1, -1, -1, 0, 0, -1, 1, -1, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, 1, 0, 1, 0, -1, -1, -1, -1, 0, 1, -1, 1, -1, 0, 1, 1, 0, 0, -1, 0, 1, 1, -1, 1, 0, 0, 0, 1, 0, -1, 1, 1, 0, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 0, 1, -1, 1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 1, -1, 0, 0, 1, 1, 0, 0, -1, 1, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, 0, -1, 1, -1, 0, 1, -1, 0, -1, 1, 1, 1, -1, 0, 1, 1, -1, -1, 0, 0, 1, -1, -1, -1, 0, -1, -1, 1, 1, 0, 1, 0, 1, -1, 1, -1, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, -1, 1, -1, 0, 0, 1, 0, -1, -1, -1, 1, -1, 1, -1, -1, 1, 0, 1, -1, 1, -1, 1, -1, 1, 0, 1, 0, 1, -1, -1, -1, -1, 1, 0, 0, -1, -1, 1, 0, 1, 1, -1, 1, -1, -1, -1, 0, 0, -1, 0, 1, 1, 1, 0, 1, 1, -1, 1, 1, 0, 1, 1, 1, 0, -1, 0, 0, -1, -1, -1 }; static TRIT InputD[] = { -1 }; static TRIT OutputD[] = { -1, 0, 0, 1, 1, 0, -1, 1, 1, 0, 1, 0, -1, 1, -1, 0, 0, 1, 0, -1, 0, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -1, 0, -1, 1, -1, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, 1, -1, 1, 1, 0, -1, 1, -1, 0, 0, 1, -1, 1, -1, 0, 0, 1, 1, -1, -1, -1, -1, 1, 0, 0, -1, 0, 0, -1, 0, 0, 1, -1, -1, -1, -1, 1, 1, 0, 0, -1, 1, -1, 1, 0, 0, -1, 1, -1, 0, 1, 1, -1, 1, -1, 0, -1, -1, 0, 0, 0, -1, 0, 0, -1, 1, -1, 0, -1, 1, -1, 1, 1, -1, -1, 0, 0, 0, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 0, -1, 0, 1, 0, 0, -1, 1, -1, 0, 1, 0, 1, 1, -1, 0, 1, 1, 0, 0, -1, -1, -1, -1, 0, 1, 0, -1, -1, 0, 0, 1, 1, 1, 0, 0, -1, 1, -1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, -1, -1, 0, -1, -1, 0, -1, -1, 1, 0, 0, -1, -1, 1, 0, 0, 0, 1, 1, 0, -1, 1, -1, -1, 1, -1, -1, 1, 1, 0, 1, 0, 0, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 0, 0, -1, -1, 1, 1 }; static TRIT InputE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static TRIT OutputE[] = { 0, 1, 0, 1, -1, -1, 1, -1, -1, 0, 0, 1, 1, -1, -1, -1, 0, 1, 0, 0, -1, -1, 1, 1, 1, -1, 0, -1, -1, -1, -1, -1, 1, -1, -1, -1, 0, 0, 1, 1, 0, 1, -1, -1, 0, -1, -1, 1, 1, 1, -1, 1, 1, 0, -1, 0, 1, -1, 1, -1, 1, 1, -1, 1, 0, -1, -1, -1, 0, 0, 1, 1, 0, -1, 0, 0, -1, 0, 0, 1, 1, -1, 0, 1, -1, -1, 1, -1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, -1, 0, 1, -1, 0, 1, -1, 1, 0, -1, 1, -1, 1, 0, -1, -1, 1, 0, 1, 0, 0, 1, 1, 1, -1, 1, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, 0, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 1, 0, 0, 1, 0, -1, -1, 0, 0, -1, -1, 1, -1, 0, -1, 1, -1, 0, 1, -1, 0, 1, 1, -1, 1, -1, 1, -1, 0, 0, 0, -1, 0, -1, 1, -1, 1, 1, 1, 1, 1, 0, -1, 0, -1, -1, 0, 0, -1, -1, 1, -1, -1, -1, 1, 0, 0, 0, 1, 0, 1, 0, 1, -1, 0, -1, -1, 1, -1, -1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, -1, -1, -1, -1, 1, 0, -1, 0, 0 }; bits384 SaM_emit(struct SaM_info *state) { // i.12 531441 81bf1 0.68% numbits.19 mask.7ffff -> bias -0.0005870312 TRIT *ptr; uint64_t bits64; uint32_t i,j,rawbits,bits19[20],mask = 0x7ffff; SaM_Squeeze(state,state->hash); ptr = state->hash; for (i=0; i 27 rawbits = (rawbits * 3 + *ptr++ + 1); rawbits = (((rawbits<<4)/27) & 0xf); //printf("%x -> Sam_emit\n",rawbits); for (bits64=i=0; i<20; i++) { memcpy(&state->bits.bytes[i*sizeof(uint16_t)],&bits19[i],sizeof(uint16_t)); bits64 = (bits64 << 3) | ((bits19[i] >> 16) & 7); } bits64 = (bits64 << 4) | (rawbits & 0xf); memcpy(&state->bits.bytes[40],&bits64,sizeof(uint64_t)); return(state->bits); } int32_t _SaM_test(char *msg,TRIT *testvector,int32_t n,TRIT *checkvals) { struct SaM_info state; int32_t i,errs; SaM_Initialize(&state); _SaM_Absorb(&state,testvector,n); SaM_emit(&state); for (i=errs=0; i<243; i++) { if ( state.hash[i] != checkvals[i] ) errs++; } if ( errs != 0 ) { for (i=0; i<243; i++) printf("%2d, ",state.hash[i]); printf("\nSaM_test.%s errs.%d vs output\n",msg,errs); } return(errs); } /*int32_t bitweight(uint64_t x) { int i,wt = 0; for (i=0; i<64; i++) if ( (1LL << i) & x ) wt++; return(wt); }*/ int32_t bitweight(uint64_t x); #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) #define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7))) double OS_milliseconds(); int32_t SaM_test() { int32_t i,j,wt,iter,totalset,totalclr,setcount[48*8],clrcount[48*8],histo[16]; bits256 seed; struct SaM_info state; uint8_t buf[4096*2],bits[2][10][48]; char trits[243]; double startmilli = OS_milliseconds(); for (i=0; i> 8; SaM_Absorb(&state,seed.bytes,sizeof(seed),0,0); } memset(bits[iter][i],0,sizeof(bits[iter][i])); SaM_emit(&state); memcpy(bits[iter][i],state.bits.bytes,sizeof(bits[iter][i])); for (j=0; j<48; j++) { histo[bits[iter][i][j] & 0xf]++; histo[(bits[iter][i][j]>>4) & 0xf]++; printf("%02x ",bits[iter][i][j]); } printf("\n"); for (j=0; j<48*8; j++) { if ( GETBIT(bits[iter][i],j) != 0 ) setcount[j]++; else clrcount[j]++; } } for (i=0; i<16; i++) printf("%8d ",histo[i]); printf("hex histogram\n"); seed.bytes[0] ^= 1; buf[0] ^= 1; } for (i=0; i<5; i++) { for (j=wt=0; j<48; j++) { wt += bitweight(bits[0][i][j] ^ bits[1][i][j]); printf("%02x",bits[0][i][j] ^ bits[1][i][j]); } printf(" i.%d diff.%d\n",i,wt); } //set.19090245 clr.19309755 -0.0057 //total set.19200072 clr.19199928 0.0000037500 // total set.19191713 clr.19208287 -0.0004316146 for (totalset=totalclr=j=0; j<48*8; j++) { totalset += setcount[j]; totalclr += clrcount[j]; printf("%.2f ",(double)(setcount[j]-clrcount[j])/i); } printf("total set.%d clr.%d %.10f\n",totalset,totalclr,(double)(totalset-totalclr)/(totalset+totalclr)); return(0); } bits384 SaM_encrypt(uint8_t *dest,uint8_t *src,int32_t len,bits384 password,uint32_t timestamp) { bits384 xorpad; int32_t i; struct SaM_info XORpad; SaM_Initialize(&XORpad), SaM_Absorb(&XORpad,password.bytes,sizeof(password),(void *)×tamp,sizeof(timestamp)); while ( len >= 0 ) { SaM_emit(&XORpad); for (i=0; i=0; i++,len--) { xorpad.bytes[i] = (XORpad.bits.bytes[i] ^ *src++); if ( dest != 0 ) *dest++ = xorpad.bytes[i]; } } return(xorpad); } uint64_t SaM_hit(struct SaM_info *state) { int32_t i; uint64_t hit = 0; for (i=0; i<27; i++) hit = (hit * 3 + state->hash[i] + 1); return(hit); } uint64_t SaM(bits384 *sigp,uint8_t *input,int32_t inputSize,uint8_t *input2,int32_t inputSize2) { int32_t verify_SaM(TRIT *newhash,uint8_t *buf,const int n); struct SaM_info state; SaM_Initialize(&state); SaM_Absorb(&state,input,inputSize,input2,inputSize2); //printf("len.%d: ",inputSize+inputSize2); *sigp = SaM_emit(&state); //if ( 0 && input2 == 0 && numrounds == SAM_MAGIC_NUMBER ) // verify_SaM(state.hash,(uint8_t *)input,inputSize); return(SaM_hit(&state)); } uint64_t SaM_threshold(int32_t leverage) { int32_t i; uint64_t threshold,divisor = 1; if ( leverage > 26 ) leverage = 26; for (i=0; i uint32_t SaM_nonce(void *data,int32_t datalen,int32_t leverage,int32_t maxmillis,uint32_t nonce) { uint64_t hit,threshold; bits384 sig; double endmilli; if ( leverage != 0 ) { threshold = SaM_threshold(leverage); if ( maxmillis == 0 ) { if ( (hit= SaM(&sig,data,datalen,(void *)&nonce,sizeof(nonce))) >= threshold ) { printf("nonce failure hit.%llu >= threshold.%llu | leverage.%d nonce.%u\n",(long long)hit,(long long)threshold,leverage,nonce); if ( (threshold - hit) > ((uint64_t)1L << 32) ) return(0xffffffff); else return((uint32_t)(threshold - hit)); } } else { endmilli = (OS_milliseconds() + maxmillis); while ( OS_milliseconds() < endmilli ) { OS_randombytes((void *)&nonce,sizeof(nonce)); if ( (hit= SaM(&sig,data,datalen,(void *)&nonce,sizeof(nonce))) < threshold ) { printf("-> nonce.%u leverage.%d | hit.%llu < threshold.%llu\n",nonce,leverage,(long long)hit,(long long)threshold); SaM_nonce(data,datalen,leverage,0,nonce); return(nonce); } } } } return(0); } /*uint64_t SaMnonce(bits384 *sigp,uint32_t *noncep,uint8_t *buf,int32_t len,uint64_t threshold,uint32_t rseed,int32_t maxmillis) { uint64_t hit = SAMHIT_LIMIT; double startmilli = 0; if ( maxmillis == 0 ) { hit = calc_SaM(sigp,buf,len,0,0); if ( hit >= threshold ) { printf("nonce failure hit.%llu >= threshold.%llu\n",(long long)hit,(long long)threshold); return(threshold - hit); } else return(0); } else startmilli = milliseconds(); while ( hit >= threshold ) { if ( rseed == 0 ) randombytes((uint8_t *)noncep,sizeof(*noncep)); else _randombytes((uint8_t *)noncep,sizeof(*noncep),rseed); hit = calc_SaM(sigp,buf,len,0,0); //printf("%llu %.2f%% (%s) len.%d numrounds.%lld threshold.%llu seed.%u\n",(long long)hit,100.*(double)hit/threshold,(char *)buf,len,(long long)numrounds,(long long)threshold,rseed); if ( maxmillis != 0 && milliseconds() > (startmilli + maxmillis) ) return(0); if ( rseed != 0 ) rseed = (uint32_t)(sigp->txid ^ hit); } //printf("%5.1f %14llu %7.2f%% numrounds.%lld threshold.%llu seed.%u\n",milliseconds()-startmilli,(long long)hit,100.*(double)hit/threshold,(long long)numrounds,(long long)threshold,rseed); return(hit); }*/ #ifdef include_vps // from Come-from-Beyond #define HASH_SIZE 32 #define DAILY 0 #define WEEKLY 1 #define MONTHLY 2 #define YEARLY 3 #define MAX_NUMBER_OF_POOLS 1000 #define MAX_NUMBER_OF_TOKENS 1000 #define MAX_NUMBER_OF_UNITS 1000000 #define MAX_NUMBER_OF_SUPERVISORS 1000000 #define MAX_TOKEN_LIFESPAN 36500 unsigned int numberOfPools = 0; struct Pool { signed long reserve; unsigned long quorum, decisionThreshold; } pools[MAX_NUMBER_OF_POOLS]; unsigned int numberOfTokens = 0; struct Token { BOOL enabled; unsigned int pool; unsigned long curSupply, maxSupply; // Defines max %% of total coin supply that can be locked signed int fadeRate; // Per day in 1/1000th (zero - to keep value const; negative - for deflation; positive - for inflation) unsigned int decreaseLimits[YEARLY + 1], increaseLimits[YEARLY + 1]; // In 1/1000th unsigned long unitSize; // Locked amount unsigned short minLockPeriod, maxLockPeriod; // In days unsigned char minExtraLockPeriod, maxExtraLockPeriod; // In days unsigned char redemptionGap; // In days unsigned long day0Offset; // UNIX time unsigned long prices[MAX_TOKEN_LIFESPAN]; // In main currency units } tokens[MAX_NUMBER_OF_TOKENS]; unsigned int numberOfUnits = 0; struct Unit { unsigned long id; unsigned int token; unsigned long account; signed int fadeRate; unsigned long size; unsigned long timestamp; unsigned char lockPeriodHash[HASH_SIZE]; unsigned short minLockPeriod, maxLockPeriod; unsigned char extraLockPeriod; unsigned char redemptionGap; } units[MAX_NUMBER_OF_UNITS]; unsigned int numberOfSupervisors = 0; struct Supervisor { unsigned long id; signed long rating; unsigned int activity; } supervisors[MAX_NUMBER_OF_SUPERVISORS]; struct Vote { unsigned long supervisorId; unsigned long price; unsigned long tolerance; unsigned long weight; unsigned long bet; }; unsigned char random() { return 42; // TODO: Replace with a better RNG } void hash(unsigned char* data, unsigned int dataSize, unsigned char* hash) { // TODO: Invoke SHA-256 } unsigned int addPool(unsigned long quorum, unsigned long decisionThreshold) { // Returns the index of the new pool if (numberOfPools >= MAX_NUMBER_OF_POOLS) { // TODO: Throw exception } pools[numberOfPools].reserve = 0; pools[numberOfPools].quorum = quorum; pools[numberOfPools].decisionThreshold = decisionThreshold; return numberOfPools++; } unsigned int addToken(unsigned int pool, unsigned long maxSupply, signed int fadeRate, unsigned int* decreaseLimits, unsigned int* increaseLimits, unsigned long unitSize, unsigned short minLockPeriod, unsigned short maxLockPeriod, unsigned char minExtraLockPeriod, unsigned char maxExtraLockPeriod, unsigned char redemptionGap, unsigned long day0Offset, unsigned long initialPrice) { // Returns the index of the new token if (numberOfTokens >= MAX_NUMBER_OF_TOKENS) { // TODO: Throw exception } if (pool >= numberOfPools) { // TODO: Throw exception } if (minLockPeriod > maxLockPeriod || minExtraLockPeriod > maxExtraLockPeriod) { // TODO: Throw exception } tokens[numberOfTokens].enabled = TRUE; tokens[numberOfTokens].pool = pool; tokens[numberOfTokens].curSupply = 0; tokens[numberOfTokens].maxSupply = maxSupply; tokens[numberOfTokens].fadeRate = fadeRate; memcpy(tokens[numberOfTokens].decreaseLimits, decreaseLimits, sizeof(tokens[numberOfTokens].decreaseLimits)); memcpy(tokens[numberOfTokens].increaseLimits, increaseLimits, sizeof(tokens[numberOfTokens].increaseLimits)); tokens[numberOfTokens].unitSize = unitSize; tokens[numberOfTokens].minLockPeriod = minLockPeriod; tokens[numberOfTokens].maxLockPeriod = maxLockPeriod; tokens[numberOfTokens].minExtraLockPeriod = minExtraLockPeriod; tokens[numberOfTokens].maxExtraLockPeriod = maxExtraLockPeriod; tokens[numberOfTokens].redemptionGap = redemptionGap; tokens[numberOfTokens].day0Offset = day0Offset; memset(tokens[numberOfTokens].prices, 0, sizeof(tokens[numberOfTokens].prices)); tokens[numberOfTokens].prices[0] = initialPrice; return numberOfTokens++; } void enableToken(unsigned int token) { tokens[token].enabled = TRUE; } void disableToken(unsigned int token) { tokens[token].enabled = FALSE; } void changeFadeRate(unsigned int token, signed int newFadeRate) { tokens[token].fadeRate = newFadeRate; } void changeUnitSize(unsigned int token, unsigned long newUnitSize) { tokens[token].unitSize = newUnitSize; } void changeLockPeriods(unsigned int token, unsigned short newMinLockPeriod, unsigned short newMaxLockPeriod) { tokens[token].minLockPeriod = newMinLockPeriod; tokens[token].maxLockPeriod = newMaxLockPeriod; } void changeExtraLockPeriods(unsigned int token, unsigned char newMinExtraLockPeriod, unsigned char newMaxExtraLockPeriod) { tokens[token].minExtraLockPeriod = newMinExtraLockPeriod; tokens[token].maxExtraLockPeriod = newMaxExtraLockPeriod; } void changeRedemptionGap(unsigned int token, unsigned char newRedemptionGap) { tokens[token].redemptionGap = newRedemptionGap; } void getLockPeriodHashAndPrefix(unsigned short lockPeriod, unsigned char* lockPeriodHash, unsigned char* lockPeriodPrefix) { unsigned char buffer[HASH_SIZE]; int i; for (i = 0; i < HASH_SIZE - sizeof(lockPeriod); i++) { buffer[i] = random(); } *((unsigned short*)&buffer[i]) = lockPeriod; // WARNING: Depends on endianness! hash(buffer, sizeof(buffer), lockPeriodHash); memcpy(lockPeriodPrefix, buffer, i); } unsigned long getLastPrice(unsigned int token, unsigned long time) { for (int i = (time - tokens[token].day0Offset) / (24 * 60 * 60 * 1000) + 1; i-- > 0;) { if (tokens[token].prices[i] > 0) { return tokens[token].prices[i]; } } } unsigned int addUnit(unsigned long id, unsigned int token, unsigned long account, unsigned long time, unsigned char* lockPeriodHash, unsigned short minLockPeriod, unsigned short maxLockPeriod, unsigned long seed, unsigned long mainCurrencyUnitSize) { // Returns the index of the new unit if (numberOfUnits >= MAX_NUMBER_OF_UNITS) { // TODO: Throw exception } if (token >= numberOfTokens) { // TODO: Throw exception } if (tokens[token].enabled == FALSE) { // TODO: Throw exception } units[numberOfUnits].id = id; units[numberOfUnits].token = token; units[numberOfUnits].account = account; units[numberOfUnits].fadeRate = tokens[token].fadeRate; units[numberOfUnits].size = tokens[token].unitSize; units[numberOfUnits].timestamp = time; memcpy(units[numberOfUnits].lockPeriodHash, lockPeriodHash, HASH_SIZE); units[numberOfUnits].minLockPeriod = minLockPeriod; units[numberOfUnits].maxLockPeriod = maxLockPeriod; units[numberOfUnits].extraLockPeriod = seed % (tokens[token].maxExtraLockPeriod - tokens[token].minExtraLockPeriod + 1) + tokens[token].minExtraLockPeriod; units[numberOfUnits].redemptionGap = tokens[token].redemptionGap; pools[tokens[token].pool].reserve += units[numberOfUnits].size * getLastPrice(token, time) / mainCurrencyUnitSize; // WARNING: May overflow! return numberOfUnits++; } unsigned long redeemUnit(unsigned long id, unsigned long account, unsigned short lockPeriod, unsigned char* lockPeriodPrefix, unsigned long time, unsigned long mainCurrencyUnitSize) { // Returns amount to add to the account balance for (int i = 0; i < numberOfUnits; i++) { if (units[i].id == id) { if (units[i].account == account) { unsigned char buffer[HASH_SIZE]; memcpy(buffer, lockPeriodPrefix, HASH_SIZE - sizeof(lockPeriod)); *((unsigned short*)&buffer[HASH_SIZE - sizeof(lockPeriod)]) = lockPeriod; // WARNING: Depends on endianness! unsigned char lockPeriodHash[HASH_SIZE]; hash(buffer, sizeof(buffer), lockPeriodHash); for (int j = 0; j < HASH_SIZE; j++) { if (lockPeriodHash[j] != units[i].lockPeriodHash[j]) { return 0; } } if (lockPeriod < units[i].minLockPeriod || lockPeriod > units[i].maxLockPeriod) { return 0; } unsigned int delta = (time - units[i].timestamp) / (24 * 60 * 60 * 1000); if (delta < lockPeriod + units[i].extraLockPeriod || delta > lockPeriod + units[i].extraLockPeriod + units[i].redemptionGap) { return 0; } unsigned long amount = units[i].size * getLastPrice(units[i].token, units[i].timestamp + (lockPeriod + units[i].extraLockPeriod) * 24 * 60 * 60 * 1000) / mainCurrencyUnitSize; // WARNING: May overflow! for (int j = lockPeriod + units[i].extraLockPeriod; j-- > 0; ) { amount = amount * (1000 - units[i].fadeRate) / 1000; // WARNING: Do not use floating-point math! } if (pools[tokens[units[i].token].pool].reserve < amount) { amount = pools[tokens[units[i].token].pool].reserve; } pools[tokens[units[i].token].pool].reserve -= amount; memcpy(&units[i], &units[--numberOfUnits], sizeof(Unit)); return amount; } break; } } return 0; } void salvageExpiredUnits(unsigned long time) { for (int i = numberOfUnits; i-- > 0; ) { if ((time - units[i].timestamp) / (24 * 60 * 60 * 1000) > units[i].maxLockPeriod + units[i].extraLockPeriod + units[i].redemptionGap) { memcpy(&units[i], &units[--numberOfUnits], sizeof(Unit)); } } } unsigned int addSupervisor(unsigned long id) { // Returns the index of the new supervisor if (numberOfSupervisors >= MAX_NUMBER_OF_SUPERVISORS) { // TODO: Throw exception } supervisors[numberOfSupervisors].id = id; supervisors[numberOfSupervisors].rating = 0; supervisors[numberOfSupervisors].activity = 0; return numberOfSupervisors++; } Supervisor* getSupervisor(unsigned long id) { for (int i = 0; i < numberOfSupervisors; i++) { if (supervisors[i].id == id) { return &supervisors[i]; } } return NULL; } BOOL castSupervisorVotes(unsigned int token, unsigned long time, Vote* votes, unsigned int numberOfVotes, unsigned long* prizes) { // Returns if a new price has been set unsigned long totalWeight = 0; unsigned long totalBet = 0; for (int i = 0; i < numberOfVotes; i++) { totalWeight += votes[i].weight; getSupervisor(votes[i].supervisorId)->activity++; totalBet += votes[i].bet; } if (totalWeight < pools[tokens[token].pool].quorum) { return FALSE; } unsigned long prices[MAX_NUMBER_OF_SUPERVISORS]; unsigned long weights[MAX_NUMBER_OF_SUPERVISORS]; for (int i = 0; i < numberOfVotes; i++) { int j; for (j = 0; j < i; j++) { if (prices[j] > votes[i].price) { break; } memmove(&prices[j + 1], &prices[j], (i - j) * sizeof(Vote)); memmove(&weights[j + 1], &weights[j], (i - j) * sizeof(Vote)); prices[j] = votes[i].price; weights[j] = votes[i].weight; } } unsigned long newPrice = 0; for (int i = 0; i < numberOfVotes; i++) { unsigned long weight = 0; unsigned long bet = 0; for (int j = 0; j < numberOfVotes; j++) { signed long delta = votes[i].price - votes[j].price; if (delta < 0) { delta = -delta; } if (delta <= votes[j].tolerance) { weight += votes[j].weight; bet += votes[j].bet; } } if (weight > totalWeight / 2) { newPrice = votes[i].price; unsigned long totalPrize = 0; for (int j = 0; j < numberOfVotes; j++) { signed long delta = votes[i].price - votes[j].price; if (delta < 0) { delta = -delta; } if (delta <= votes[j].tolerance) { getSupervisor(votes[j].supervisorId)->rating++; if (prizes != NULL) { prizes[j] = votes[j].bet + (votes[j].bet * (totalBet - bet) / bet); totalPrize += prizes[j]; } } else { if (prizes != NULL) { prizes[j] = 0; } } } if (prizes != NULL) { pools[tokens[token].pool].reserve += totalBet - totalPrize; } break; } } if (newPrice == 0) { return FALSE; } else { unsigned long lastPrice = getLastPrice(token, time); if (newPrice < lastPrice) { if ((lastPrice - newPrice) * 1000 / lastPrice > tokens[token].decreaseLimits[DAILY]) { newPrice = lastPrice - tokens[token].decreaseLimits[DAILY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 7L * 24 * 60 * 60 * 1000); if ((lastPrice - newPrice) * 1000 / lastPrice > tokens[token].decreaseLimits[WEEKLY]) { newPrice = lastPrice - tokens[token].decreaseLimits[WEEKLY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 30L * 24 * 60 * 60 * 1000); if ((lastPrice - newPrice) * 1000 / lastPrice > tokens[token].decreaseLimits[MONTHLY]) { newPrice = lastPrice - tokens[token].decreaseLimits[MONTHLY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 365L * 24 * 60 * 60 * 1000); if ((lastPrice - newPrice) * 1000 / lastPrice > tokens[token].decreaseLimits[YEARLY]) { newPrice = lastPrice - tokens[token].decreaseLimits[YEARLY] * lastPrice / 1000; } } else { if ((newPrice - lastPrice) * 1000 / lastPrice > tokens[token].increaseLimits[DAILY]) { newPrice = lastPrice + tokens[token].increaseLimits[DAILY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 7L * 24 * 60 * 60 * 1000); if ((newPrice - lastPrice) * 1000 / lastPrice > tokens[token].increaseLimits[WEEKLY]) { newPrice = lastPrice + tokens[token].increaseLimits[WEEKLY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 30L * 24 * 60 * 60 * 1000); if ((newPrice - lastPrice) * 1000 / lastPrice > tokens[token].increaseLimits[MONTHLY]) { newPrice = lastPrice + tokens[token].increaseLimits[MONTHLY] * lastPrice / 1000; } lastPrice = getLastPrice(token, time - 365L * 24 * 60 * 60 * 1000); if ((newPrice - lastPrice) * 1000 / lastPrice > tokens[token].increaseLimits[YEARLY]) { newPrice = lastPrice + tokens[token].increaseLimits[YEARLY] * lastPrice / 1000; } } tokens[token].prices[(time - tokens[token].day0Offset) / (24 * 60 * 60 * 1000)] = newPrice; return TRUE; } } #endif char bits2trits[256][5] = { {0, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, {-1, 1, 0, 0, 0}, {0, 1, 0, 0, 0}, {1, 1, 0, 0, 0}, {-1, -1, 1, 0, 0}, {0, -1, 1, 0, 0}, {1, -1, 1, 0, 0}, {-1, 0, 1, 0, 0}, {0, 0, 1, 0, 0}, {1, 0, 1, 0, 0}, {-1, 1, 1, 0, 0}, {0, 1, 1, 0, 0}, {1, 1, 1, 0, 0}, {-1, -1, -1, 1, 0}, {0, -1, -1, 1, 0}, {1, -1, -1, 1, 0}, {-1, 0, -1, 1, 0}, {0, 0, -1, 1, 0}, {1, 0, -1, 1, 0}, {-1, 1, -1, 1, 0}, {0, 1, -1, 1, 0}, {1, 1, -1, 1, 0}, {-1, -1, 0, 1, 0}, {0, -1, 0, 1, 0}, {1, -1, 0, 1, 0}, {-1, 0, 0, 1, 0}, {0, 0, 0, 1, 0}, {1, 0, 0, 1, 0}, {-1, 1, 0, 1, 0}, {0, 1, 0, 1, 0}, {1, 1, 0, 1, 0}, {-1, -1, 1, 1, 0}, {0, -1, 1, 1, 0}, {1, -1, 1, 1, 0}, {-1, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {1, 0, 1, 1, 0}, {-1, 1, 1, 1, 0}, {0, 1, 1, 1, 0}, {1, 1, 1, 1, 0}, {-1, -1, -1, -1, 1}, {0, -1, -1, -1, 1}, {1, -1, -1, -1, 1}, {-1, 0, -1, -1, 1}, {0, 0, -1, -1, 1}, {1, 0, -1, -1, 1}, {-1, 1, -1, -1, 1}, {0, 1, -1, -1, 1}, {1, 1, -1, -1, 1}, {-1, -1, 0, -1, 1}, {0, -1, 0, -1, 1}, {1, -1, 0, -1, 1}, {-1, 0, 0, -1, 1}, {0, 0, 0, -1, 1}, {1, 0, 0, -1, 1}, {-1, 1, 0, -1, 1}, {0, 1, 0, -1, 1}, {1, 1, 0, -1, 1}, {-1, -1, 1, -1, 1}, {0, -1, 1, -1, 1}, {1, -1, 1, -1, 1}, {-1, 0, 1, -1, 1}, {0, 0, 1, -1, 1}, {1, 0, 1, -1, 1}, {-1, 1, 1, -1, 1}, {0, 1, 1, -1, 1}, {1, 1, 1, -1, 1}, {-1, -1, -1, 0, 1}, {0, -1, -1, 0, 1}, {1, -1, -1, 0, 1}, {-1, 0, -1, 0, 1}, {0, 0, -1, 0, 1}, {1, 0, -1, 0, 1}, {-1, 1, -1, 0, 1}, {0, 1, -1, 0, 1}, {1, 1, -1, 0, 1}, {-1, -1, 0, 0, 1}, {0, -1, 0, 0, 1}, {1, -1, 0, 0, 1}, {-1, 0, 0, 0, 1}, {0, 0, 0, 0, 1}, {1, 0, 0, 0, 1}, {-1, 1, 0, 0, 1}, {0, 1, 0, 0, 1}, {1, 1, 0, 0, 1}, {-1, -1, 1, 0, 1}, {0, -1, 1, 0, 1}, {1, -1, 1, 0, 1}, {-1, 0, 1, 0, 1}, {0, 0, 1, 0, 1}, {1, 0, 1, 0, 1}, {-1, 1, 1, 0, 1}, {0, 1, 1, 0, 1}, {1, 1, 1, 0, 1}, {-1, -1, -1, 1, 1}, {0, -1, -1, 1, 1}, {1, -1, -1, 1, 1}, {-1, 0, -1, 1, 1}, {0, 0, -1, 1, 1}, {1, 0, -1, 1, 1}, {-1, 1, -1, 1, 1}, {0, 1, -1, 1, 1}, {1, 1, -1, 1, 1}, {-1, -1, 0, 1, 1}, {0, -1, 0, 1, 1}, {1, -1, 0, 1, 1}, {-1, 0, 0, 1, 1}, {0, 0, 0, 1, 1}, {1, 0, 0, 1, 1}, {-1, 1, 0, 1, 1}, {0, 1, 0, 1, 1}, {1, 1, 0, 1, 1}, {-1, -1, 1, 1, 1}, {0, -1, 1, 1, 1}, {1, -1, 1, 1, 1}, {-1, 0, 1, 1, 1}, {0, 0, 1, 1, 1}, {1, 0, 1, 1, 1}, {-1, 1, 1, 1, 1}, {0, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {2, 2, 2, 2, 2}, {-1, -1, -1, -1, -1}, {0, -1, -1, -1, -1}, {1, -1, -1, -1, -1}, {-1, 0, -1, -1, -1}, {0, 0, -1, -1, -1}, {1, 0, -1, -1, -1}, {-1, 1, -1, -1, -1}, {0, 1, -1, -1, -1}, {1, 1, -1, -1, -1}, {-1, -1, 0, -1, -1}, {0, -1, 0, -1, -1}, {1, -1, 0, -1, -1}, {-1, 0, 0, -1, -1}, {0, 0, 0, -1, -1}, {1, 0, 0, -1, -1}, {-1, 1, 0, -1, -1}, {0, 1, 0, -1, -1}, {1, 1, 0, -1, -1}, {-1, -1, 1, -1, -1}, {0, -1, 1, -1, -1}, {1, -1, 1, -1, -1}, {-1, 0, 1, -1, -1}, {0, 0, 1, -1, -1}, {1, 0, 1, -1, -1}, {-1, 1, 1, -1, -1}, {0, 1, 1, -1, -1}, {1, 1, 1, -1, -1}, {-1, -1, -1, 0, -1}, {0, -1, -1, 0, -1}, {1, -1, -1, 0, -1}, {-1, 0, -1, 0, -1}, {0, 0, -1, 0, -1}, {1, 0, -1, 0, -1}, {-1, 1, -1, 0, -1}, {0, 1, -1, 0, -1}, {1, 1, -1, 0, -1}, {-1, -1, 0, 0, -1}, {0, -1, 0, 0, -1}, {1, -1, 0, 0, -1}, {-1, 0, 0, 0, -1}, {0, 0, 0, 0, -1}, {1, 0, 0, 0, -1}, {-1, 1, 0, 0, -1}, {0, 1, 0, 0, -1}, {1, 1, 0, 0, -1}, {-1, -1, 1, 0, -1}, {0, -1, 1, 0, -1}, {1, -1, 1, 0, -1}, {-1, 0, 1, 0, -1}, {0, 0, 1, 0, -1}, {1, 0, 1, 0, -1}, {-1, 1, 1, 0, -1}, {0, 1, 1, 0, -1}, {1, 1, 1, 0, -1}, {-1, -1, -1, 1, -1}, {0, -1, -1, 1, -1}, {1, -1, -1, 1, -1}, {-1, 0, -1, 1, -1}, {0, 0, -1, 1, -1}, {1, 0, -1, 1, -1}, {-1, 1, -1, 1, -1}, {0, 1, -1, 1, -1}, {1, 1, -1, 1, -1}, {-1, -1, 0, 1, -1}, {0, -1, 0, 1, -1}, {1, -1, 0, 1, -1}, {-1, 0, 0, 1, -1}, {0, 0, 0, 1, -1}, {1, 0, 0, 1, -1}, {-1, 1, 0, 1, -1}, {0, 1, 0, 1, -1}, {1, 1, 0, 1, -1}, {-1, -1, 1, 1, -1}, {0, -1, 1, 1, -1}, {1, -1, 1, 1, -1}, {-1, 0, 1, 1, -1}, {0, 0, 1, 1, -1}, {1, 0, 1, 1, -1}, {-1, 1, 1, 1, -1}, {0, 1, 1, 1, -1}, {1, 1, 1, 1, -1}, {-1, -1, -1, -1, 0}, {0, -1, -1, -1, 0}, {1, -1, -1, -1, 0}, {-1, 0, -1, -1, 0}, {0, 0, -1, -1, 0}, {1, 0, -1, -1, 0}, {-1, 1, -1, -1, 0}, {0, 1, -1, -1, 0}, {1, 1, -1, -1, 0}, {-1, -1, 0, -1, 0}, {0, -1, 0, -1, 0}, {1, -1, 0, -1, 0}, {-1, 0, 0, -1, 0}, {0, 0, 0, -1, 0}, {1, 0, 0, -1, 0}, {-1, 1, 0, -1, 0}, {0, 1, 0, -1, 0}, {1, 1, 0, -1, 0}, {-1, -1, 1, -1, 0}, {0, -1, 1, -1, 0}, {1, -1, 1, -1, 0}, {-1, 0, 1, -1, 0}, {0, 0, 1, -1, 0}, {1, 0, 1, -1, 0}, {-1, 1, 1, -1, 0}, {0, 1, 1, -1, 0}, {1, 1, 1, -1, 0}, {-1, -1, -1, 0, 0}, {0, -1, -1, 0, 0}, {1, -1, -1, 0, 0}, {-1, 0, -1, 0, 0}, {0, 0, -1, 0, 0}, {1, 0, -1, 0, 0}, {-1, 1, -1, 0, 0}, {0, 1, -1, 0, 0}, {1, 1, -1, 0, 0}, {-1, -1, 0, 0, 0}, {0, -1, 0, 0, 0}, {1, -1, 0, 0, 0}, {-1, 0, 0, 0, 0} }; #endif #endif