Last active
August 22, 2019 09:13
-
-
Save sleepdefic1t/d53c9da88866bc5bdfd2a17338311fba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /******************************************************************************* | |
| * Ark Wallet | |
| * (c) 2017 Ledger | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| ********************************************************************************/ | |
| #include <stdbool.h> | |
| #include <string.h> | |
| #include "arkHelpers.h" | |
| #include "arkBase58.h" | |
| void ark_public_key_hash160(unsigned char WIDE *in, unsigned short inlen, | |
| unsigned char *out) { | |
| union { | |
| cx_sha256_t shasha; | |
| cx_ripemd160_t riprip; | |
| } u; | |
| cx_ripemd160_init(&u.riprip); | |
| #if defined(TARGET_NANOS) | |
| cx_hash(&u.riprip.header, CX_LAST, in, inlen, out); | |
| #endif | |
| #if defined(TARGET_NANOX) | |
| cx_hash(&u.riprip.header, CX_LAST, in, inlen, out, 32); | |
| #endif | |
| } | |
| unsigned short ark_public_key_to_encoded_base58(unsigned char WIDE *in, | |
| unsigned short inlen, | |
| unsigned char *out, | |
| unsigned short outlen, | |
| unsigned short version, | |
| unsigned char alreadyHashed) { | |
| unsigned char tmpBuffer[26]; | |
| unsigned char checksumBuffer[32]; | |
| cx_sha256_t hash; | |
| unsigned char versionSize = (version > 255 ? 2 : 1); | |
| if (version > 255) { | |
| tmpBuffer[0] = (version >> 8); | |
| tmpBuffer[1] = version; | |
| } else { | |
| tmpBuffer[0] = version; | |
| } | |
| if (!alreadyHashed) { | |
| ark_public_key_hash160(in, inlen, tmpBuffer + versionSize); | |
| } else { | |
| os_memmove(tmpBuffer + versionSize, in + versionSize, 20); | |
| } | |
| #if defined(TARGET_NANOS) | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, tmpBuffer, 20 + versionSize, checksumBuffer); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, checksumBuffer, 32, checksumBuffer); | |
| #endif | |
| #if defined(TARGET_NANOX) | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, tmpBuffer, 20 + versionSize, checksumBuffer, 32); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, checksumBuffer, 32, checksumBuffer, 32); | |
| #endif | |
| os_memmove(tmpBuffer + 20 + versionSize, checksumBuffer, 4); | |
| return ark_encode_base58(tmpBuffer, 24 + versionSize, out, outlen); | |
| } | |
| unsigned short ark_address_to_encoded_base58(unsigned char WIDE *in, | |
| unsigned short inlen, | |
| unsigned char *out, | |
| unsigned short outlen) { | |
| unsigned char tmpBuffer[inlen+4]; | |
| unsigned char checksumBuffer[32]; | |
| cx_sha256_t hash; | |
| #if defined(TARGET_NANOS) | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, in, inlen, checksumBuffer); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, checksumBuffer, 32, checksumBuffer); | |
| #endif | |
| #if defined(TARGET_NANOX) | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, in, inlen, checksumBuffer, 32); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, checksumBuffer, 32, checksumBuffer, 32); | |
| #endif | |
| os_memmove(tmpBuffer + inlen, checksumBuffer, 4); | |
| return ark_encode_base58(tmpBuffer, inlen + 4, out, outlen); | |
| } | |
| unsigned short ark_decode_base58_address(unsigned char WIDE *in, | |
| unsigned short inlen, | |
| unsigned char *out, | |
| unsigned short outlen) { | |
| unsigned char hashBuffer[32]; | |
| cx_sha256_t hash; | |
| outlen = ark_decode_base58(in, inlen, out, outlen); | |
| #if defined(TARGET_NANOS) | |
| // Compute hash to verify address | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, out, outlen - 4, hashBuffer); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, hashBuffer, 32, hashBuffer); | |
| #endif | |
| #if defined(TARGET_NANOX) | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, out, outlen - 4, hashBuffer, 32); | |
| cx_sha256_init(&hash); | |
| cx_hash(&hash.header, CX_LAST, hashBuffer, 32, hashBuffer, 32); | |
| #endif | |
| if (os_memcmp(out + outlen - 4, hashBuffer, 4)) { | |
| THROW(INVALID_CHECKSUM); | |
| } | |
| return outlen; | |
| } | |
| unsigned short ark_compress_public_key(cx_ecfp_public_key_t *publicKey, | |
| uint8_t *out, uint32_t outlen) { | |
| if (outlen < 33) { | |
| THROW(EXCEPTION_OVERFLOW); | |
| } | |
| if (publicKey->curve == CX_CURVE_256K1) { | |
| out[0] = ((publicKey->W[64] & 1) ? 0x03 : 0x02); | |
| os_memmove(out + 1, publicKey->W + 1, 32); | |
| } else if (publicKey->curve == CX_CURVE_Ed25519) { | |
| uint8_t i; | |
| out[0] = 0xED; | |
| for (i = 0; i < 32; i++) { | |
| out[i + 1] = publicKey->W[64 - i]; | |
| } | |
| if ((publicKey->W[32] & 1) != 0) { | |
| out[32] |= 0x80; | |
| } | |
| } else { | |
| THROW(EXCEPTION); | |
| } | |
| return 33; | |
| } | |
| #if 0 | |
| unsigned short ark_print_amount(uint64_t amount, uint8_t *out, uint32_t outlen) { | |
| uint64_t partInt; | |
| uint64_t partDecimal; | |
| partInt = amount / 1000000; | |
| partDecimal = amount - (partInt * 1000000); | |
| // TODO : handle properly | |
| if ((partInt > 0xFFFFFFFF) || (partDecimal > 0xFFFFFFFF)) { | |
| THROW(EXCEPTION); | |
| } | |
| if (partDecimal == 0) { | |
| snprintf(out, outlen, "%d", (uint32_t)partInt); | |
| } | |
| else { | |
| snprintf(out, outlen, "%d.%d", (uint32_t)partInt, (uint32_t)partDecimal); | |
| } | |
| return strlen(out); | |
| } | |
| #endif | |
| bool adjustDecimals(char *src, uint32_t srcLength, char *target, | |
| uint32_t targetLength, uint8_t decimals) { | |
| uint32_t startOffset; | |
| uint32_t lastZeroOffset = 0; | |
| uint32_t offset = 0; | |
| if ((srcLength == 1) && (*src == '0')) { | |
| if (targetLength < 2) { | |
| return false; | |
| } | |
| target[offset++] = '0'; | |
| target[offset++] = '\0'; | |
| return true; | |
| } | |
| if (srcLength <= decimals) { | |
| uint32_t delta = decimals - srcLength; | |
| if (targetLength < srcLength + 1 + 2 + delta) { | |
| return false; | |
| } | |
| target[offset++] = '0'; | |
| target[offset++] = '.'; | |
| for (uint32_t i = 0; i < delta; i++) { | |
| target[offset++] = '0'; | |
| } | |
| startOffset = offset; | |
| for (uint32_t i = 0; i < srcLength; i++) { | |
| target[offset++] = src[i]; | |
| } | |
| target[offset] = '\0'; | |
| } else { | |
| uint32_t sourceOffset = 0; | |
| uint32_t delta = srcLength - decimals; | |
| if (targetLength < srcLength + 1 + 1) { | |
| return false; | |
| } | |
| while (offset < delta) { | |
| target[offset++] = src[sourceOffset++]; | |
| } | |
| if (decimals != 0) { | |
| target[offset++] = '.'; | |
| } | |
| startOffset = offset; | |
| while (sourceOffset < srcLength) { | |
| target[offset++] = src[sourceOffset++]; | |
| } | |
| target[offset] = '\0'; | |
| } | |
| for (uint32_t i = startOffset; i < offset; i++) { | |
| if (target[i] == '0') { | |
| if (lastZeroOffset == 0) { | |
| lastZeroOffset = i; | |
| } | |
| } else { | |
| lastZeroOffset = 0; | |
| } | |
| } | |
| if (lastZeroOffset != 0) { | |
| target[lastZeroOffset] = '\0'; | |
| if (target[lastZeroOffset - 1] == '.') { | |
| target[lastZeroOffset - 1] = '\0'; | |
| } | |
| } | |
| return true; | |
| } | |
| unsigned short ark_print_amount(uint64_t amount, uint8_t *out, | |
| uint32_t outlen) { | |
| uint8_t tmp[20] = { '\0' }; | |
| uint8_t tmp2[25] = { '\0' }; | |
| uint32_t numDigits = 0, i; | |
| uint64_t base = 1; | |
| while (base <= amount) { | |
| base *= 10; | |
| numDigits++; | |
| } | |
| if (numDigits > sizeof(tmp) - 1) { | |
| THROW(EXCEPTION); | |
| } | |
| base /= 10; | |
| for (i = 0; i < numDigits; i++) { | |
| tmp[i] = '0' + ((amount / base) % 10); | |
| base /= 10; | |
| } | |
| tmp[i] = '\0'; | |
| os_memmove(tmp2, "ARK ", 5); | |
| adjustDecimals((char *)tmp, i, (char *)tmp2 + 4, 25, 8); | |
| size_t tmp2Len = strlen((char *)tmp2); | |
| if (tmp2Len < outlen - 1) { | |
| os_memmove(out, tmp2, tmp2Len); | |
| } else { | |
| out[0] = '\0'; | |
| } | |
| return strlen((char *)out); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment