CBByteArray * CBVersionChecksumBytesGetString(CBVersionChecksumBytes * self) { if (self->cachedString) { // Return cached string CBRetainObject(self->cachedString); return self->cachedString; } else { // Make string CBByteArrayReverseBytes(CBGetByteArray(self)); // Make this into little-endian CBBigInt bytes; CBBigIntAlloc(&bytes, CBGetByteArray(self)->length); bytes.length = CBGetByteArray(self)->length; memcpy(bytes.data, CBByteArrayGetData(CBGetByteArray(self)), bytes.length); char * string = CBEncodeBase58(&bytes); if (NOT string) return NULL; CBByteArray * str = CBNewByteArrayFromString(string, true, CBGetByteArray(self)->logError); if (NOT str) { free(string); return NULL; } CBByteArrayReverseBytes(CBGetByteArray(self)); // Now the string is got, back to big-endian. if (self->cacheString) { self->cachedString = str; CBRetainObject(str); // Retain for this object. } return str; // No additional retain. Retained from constructor. } }
bool CBDecodeBase58(CBBigInt * bi, char * str){ // ??? Quite likely these functions can be improved CBBigInt bi2; if (NOT CBBigIntAlloc(&bi2, 1)) return false; bi->data[0] = 0; bi->length = 1; for (uint8_t x = strlen(str) - 1;; x--){ // Working backwards // Get index in alphabet array uint8_t alphaIndex = str[x]; if (alphaIndex != 49){ // If not 1 if (str[x] < 58){ // Numbers alphaIndex -= 49; }else if (str[x] < 73){ // A-H alphaIndex -= 56; }else if (str[x] < 79){ // J-N alphaIndex -= 57; }else if (str[x] < 91){ // P-Z alphaIndex -= 58; }else if (str[x] < 108){ // a-k alphaIndex -= 64; }else{ // m-z alphaIndex -= 65; } if (NOT CBBigIntFromPowUInt8(&bi2, 58, strlen(str) - 1 - x)){ // Error occured. free(bi2.data); return false; } if (NOT CBBigIntEqualsMultiplicationByUInt8(&bi2, alphaIndex)){ // Error occured. free(bi2.data); return false; } if (NOT CBBigIntEqualsAdditionByBigInt(bi, &bi2)){ // Error occured. free(bi2.data); return false; } } if (NOT x) break; } free(bi2.data); // Got CBBigInt from base-58 string. Add zeros on end. uint8_t zeros = 0; for (uint8_t x = 0; x < strlen(str); x++) if (str[x] == '1') zeros++; else break; if (zeros) { bi->length += zeros; if (NOT CBBigIntRealloc(bi, bi->length)) return false; memset(bi->data + bi->length - zeros, 0, zeros); } return true; }
bool CBBlockChainStorageLoadBranchWork(void * validator, uint8_t branchNum){ CBFullValidator * validatorObj = validator; CBDatabase * database = (CBDatabase *)validatorObj->storage; // Get work CB_WORK_KEY[2] = branchNum; uint8_t workLen = CBDatabaseGetLength(database, CB_WORK_KEY); if (NOT CBBigIntAlloc(&validatorObj->branches[branchNum].work, workLen)){ CBLogError("There was an error when allocating memory for a branch's work."); return false; } validatorObj->branches[branchNum].work.length = workLen; if (NOT CBDatabaseReadValue(database, CB_WORK_KEY, validatorObj->branches[branchNum].work.data, workLen, 0)) { CBLogError("There was an error when reading the work for a branch."); free(validatorObj->branches[branchNum].work.data); return false; } return true; }
bool CBInitVersionChecksumBytesFromString(CBVersionChecksumBytes * self,CBByteArray * string,bool cacheString,void (*logError)(char *,...)) { // Cache string if needed if (cacheString) { self->cachedString = string; CBRetainObject(string); } else self->cachedString = NULL; self->cacheString = cacheString; // Get bytes from string conversion CBBigInt bytes; CBBigIntAlloc(&bytes, 25); // 25 is the number of bytes for bitcoin addresses. if (NOT CBDecodeBase58Checked(&bytes, (char *)CBByteArrayGetData(string), logError)) return false; // Take over the bytes with the CBByteArray if (NOT CBInitByteArrayWithData(CBGetByteArray(self), bytes.data, bytes.length, logError)) return false; CBByteArrayReverseBytes(CBGetByteArray(self)); // CBBigInt is in little-endian. Conversion needed to make bitcoin address the right way. return true; }
int main(int argc, char * argv[]){ bool encode = strcmp(argv[1],"-d"); // Read comma sperated inputs from the second argument char * inputs[100], * comma; inputs[0] = argv[2]; int num = 1; for (; (comma = strchr(argv[2], ',')); num++) { inputs[num] = comma + 1; *comma = '\0'; argv[2] = comma + 1; } for (int x = 0; x < num; x++) { if (encode) { // Convert hex string into bytes and then encode base58 string CBByteArray * bytes = CBNewByteArrayFromHex(inputs[x]); CBByteArrayReverseBytes(bytes); CBBigInt bi = {CBByteArrayGetData(bytes), bytes->length, bytes->length}; char * output = CBEncodeBase58(&bi); puts(output); free(output); CBReleaseObject(bytes); }else{ // Decode base58 string and then produce data as a hex string. CBBigInt bi; CBBigIntAlloc(&bi, strlen(inputs[x]) * 100 / 136); CBDecodeBase58(&bi, inputs[x]); printf("0x"); for (uint8_t x = bi.length; x--;) printf("%02x", bi.data[x]); puts(""); free(bi.data); } } }
int main(){ unsigned int s = (unsigned int)time(NULL); printf("Session = %ui\n",s); srand(s); // Test checked decode CBBigInt bi; CBBigIntAlloc(&bi, 29); CBDecodeBase58Checked(&bi, "1D5A1q5d192j5gYuWiP3CSE5fcaaZxe6E9", onErrorReceived); // Valid printf("END VALID\n"); CBDecodeBase58Checked(&bi, "1qBd3Y9D8HhzA4bYSKgkPw8LsX4wCcbqBX", onErrorReceived); // Invalid // ??? Test for: // c5f88541634fb7bade5f94ff671d1febdcbda116d2da779038ed767989 bi.data[0] = 0xc5; bi.data[1] = 0xf8; bi.data[2] = 0x85; bi.data[3] = 0x41; bi.data[4] = 0x63; bi.data[5] = 0x4f; bi.data[6] = 0xb7; bi.data[7] = 0xba; bi.data[8] = 0xde; bi.data[9] = 0x5f; bi.data[10] = 0x94; bi.data[11] = 0xff; bi.data[12] = 0x67; bi.data[13] = 0x1d; bi.data[14] = 0x1f; bi.data[15] = 0xeb; bi.data[16] = 0xdc; bi.data[17] = 0xbd; bi.data[18] = 0xa1; bi.data[19] = 0x16; bi.data[20] = 0xd2; bi.data[21] = 0xda; bi.data[22] = 0x77; bi.data[23] = 0x90; bi.data[24] = 0x38; bi.data[25] = 0xed; bi.data[26] = 0x76; bi.data[27] = 0x79; bi.data[28] = 0x89; bi.length = 29; char * str = CBEncodeBase58(&bi); printf("%s\n",str); if (strcmp(str, "7EyVQVmCjB3siBN8DdtuG3ws5jW9xsnT25vbt5eU")) { printf("7EyVQVmCjB3siBN8DdtuG3ws5jW9xsnT25vbt5eU FAIL\n"); return 1; } free(str); unsigned char * verify = malloc(29); for (int x = 0; x < 10000; x++) { for (int y = 0; y < 29; y++) { bi.data[y] = rand(); verify[y] = bi.data[y]; } bi.length = 29; printf("0x"); for (int y = 0; y < 29; y++) { printf("%.2x",verify[y]); } str = CBEncodeBase58(&bi); printf(" -> %s -> \n",str); CBDecodeBase58(&bi,str); free(str); printf("0x"); for (int y = 0; y < 29; y++) { printf("%.2x",bi.data[y]); if (bi.data[y] != verify[y]) { printf(" = FAIL\n"); return 1; } } printf(" = OK\n"); } free(bi.data); return 0; }