void wrap_fetch_transaction_args(data_chunk& data, const hash_digest& tx_hash) { data.resize(hash_digest_size); auto serial = make_serializer(data.begin()); serial.write_hash(tx_hash); BITCOIN_ASSERT(serial.iterator() == data.end()); }
void wrap_fetch_history_args(data_chunk& data, const payment_address& address, size_t from_height) { data.resize(1 + short_hash_size + 4); auto serial = make_serializer(data.begin()); serial.write_byte(address.version()); serial.write_short_hash(address.hash()); serial.write_4_bytes(from_height); BITCOIN_ASSERT(serial.iterator() == data.end()); }
bool parse_token(data_chunk& raw_script, std::string token) { boost::algorithm::trim(token); // skip this if (token.empty()) return true; static data_chunk hex_raw; if (token == "ENDING" || !is_hex_data(token)) { if (!hex_raw.empty()) { extend_data(raw_script, hex_raw); hex_raw.resize(0); } } if (token == "ENDING") { // Do nothing... } else if (is_number(token)) { int64_t value = boost::lexical_cast<int64_t>(token); if (is_opx(value)) push_literal(raw_script, value); else { script_number bignum(value); push_data(raw_script, bignum.data()); } } else if (is_hex_data(token)) { std::string hex_part(token.begin() + 2, token.end()); data_chunk raw_data; if (!decode_base16(raw_data, hex_part)) return false; extend_data(hex_raw, raw_data); } else if (is_quoted_string(token)) { data_chunk inner_value(token.begin() + 1, token.end() - 1); push_data(raw_script, inner_value); } else if (is_opcode(token)) { opcode tokenized_opcode = token_to_opcode(token); raw_script.push_back(static_cast<uint8_t>(tokenized_opcode)); } else { log_error() << "Token parsing failed with: " << token; return false; } return true; }
bool parse_token(data_chunk& raw_script, const std::string& token) { static data_chunk hex_raw; if (token == "ENDING" || !is_hex_data(token)) { if (!hex_raw.empty()) { extend_data(raw_script, hex_raw); hex_raw.resize(0); } } if (token == "ENDING") { // Do nothing... } else if (is_number(token)) { int64_t value = boost::lexical_cast<int64_t>(token); if (is_opx(value)) push_literal(raw_script, value); else { big_number bignum; bignum.set_int64(value); push_data(raw_script, bignum.data()); } } else if (is_hex_data(token)) { std::string hex_part(token.begin() + 2, token.end()); data_chunk raw_data = bytes_from_pretty(hex_part); extend_data(hex_raw, raw_data); } else if (is_quoted_string(token)) { data_chunk inner_value(token.begin() + 1, token.end() - 1); push_data(raw_script, inner_value); } else if (is_opcode(token)) { opcode tokenized_opcode = token_to_opcode(token); raw_script.push_back(static_cast<byte>(tokenized_opcode)); } else { log_error() << "Token parsing failed with: " << token; return false; } return true; }
int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS) { // https://bitcointalk.org/index.php?topic=972541.msg10619684 if (fDebugRingSig) LogPrintf("%s: Ring size %d.\n", __func__, nRingSize); assert(nRingSize < 200); RandAddSeedPerfmon(); memset(pSigS, 0, EC_SECRET_SIZE * nRingSize); int rv = 0; int nBytes; uint256 tmpPkHash; uint256 tmpHash; uint8_t tempData[66]; // hold raw point data to hash ec_secret sAlpha; if (0 != GenerateRandomSecret(sAlpha)) return errorN(1, "%s: GenerateRandomSecret failed.", __func__); CHashWriter ssPkHash(SER_GETHASH, PROTOCOL_VERSION); CHashWriter ssCjHash(SER_GETHASH, PROTOCOL_VERSION); uint256 test; for (int i = 0; i < nRingSize; ++i) { ssPkHash.write((const char*)&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); if (i == nSecretOffset) continue; int k; // NOTE: necessary to clamp? for (k = 0; k < 32; ++k) { if (1 != RAND_bytes(&pSigS[i * EC_SECRET_SIZE], 32)) return errorN(1, "%s: RAND_bytes ERR_get_error %u.", __func__, ERR_get_error()); memcpy(test.begin(), &pSigS[i * EC_SECRET_SIZE], 32); if (test > MIN_SECRET && test < MAX_SECRET) break; }; if (k > 31) return errorN(1, "%s: Failed to generate a valid key.", __func__); }; tmpPkHash = ssPkHash.GetHash(); BN_CTX_start(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnT2 = BN_CTX_get(bnCtx); BIGNUM *bnS = BN_CTX_get(bnCtx); BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnCj = BN_CTX_get(bnCtx); BIGNUM *bnA = BN_CTX_get(bnCtx); EC_POINT *ptKi = NULL; EC_POINT *ptPk = NULL; EC_POINT *ptT1 = NULL; EC_POINT *ptT2 = NULL; EC_POINT *ptT3 = NULL; EC_POINT *ptT4 = NULL; if ( !(ptKi = EC_POINT_new(ecGrp)) || !(ptPk = EC_POINT_new(ecGrp)) || !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) || !(ptT3 = EC_POINT_new(ecGrp)) || !(ptT4 = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; // get keyimage as point if (!EC_POINT_oct2point(ecGrp, ptKi, &keyImage[0], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: extract ptKi failed.\n", __func__); rv = 1; goto End; }; // c_{j+1} = h(P_1,...,P_n,alpha*G,alpha*H(P_j)) if (!bnA || !(BN_bin2bn(&sAlpha.e[0], EC_SECRET_SIZE, bnA))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // ptT1 = alpha * G if (!EC_POINT_mul(ecGrp, ptT1, bnA, NULL, NULL, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT3 = H(Pj) if (hashToEC(&pPubkeys[nSecretOffset * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT3) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; ssCjHash.write((const char*)tmpPkHash.begin(), 32); // ptT2 = alpha * H(P_j) // ptT2 = alpha * ptT3 if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnA, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; if ( !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; ssCjHash.write((const char*)&tempData[0], 66); tmpHash = ssCjHash.GetHash(); if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1 || !BN_mod(bnC, bnC, bnOrder, bnCtx)) { LogPrintf("%s: hash -> bnC failed.\n", __func__); rv = 1; goto End; }; // c_{j+2} = h(P_1,...,P_n,s_{j+1}*G+c_{j+1}*P_{j+1},s_{j+1}*H(P_{j+1})+c_{j+1}*I_j) for (int k = 0, ib = (nSecretOffset + 1) % nRingSize, i = (nSecretOffset + 2) % nRingSize; k < nRingSize; ++k, ib=i, i=(i+1) % nRingSize) { if (k == nRingSize - 1) { // s_j = alpha - c_j*x_j mod n. if (!bnT || !BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnT)) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; if (!BN_mul(bnT2, bnCj, bnT, bnCtx)) { LogPrintf("%s: BN_mul failed.\n", __func__); rv = 1; goto End; }; if (!BN_mod_sub(bnS, bnA, bnT2, bnOrder, bnCtx)) { LogPrintf("%s: BN_mod_sub failed.\n", __func__); rv = 1; goto End; }; if (!bnS || (nBytes = BN_num_bytes(bnS)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnS, &pSigS[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnS -> pSigS failed.\n", __func__); rv = 1; goto End; }; if (nSecretOffset != nRingSize - 1) break; }; if (!bnS || !(BN_bin2bn(&pSigS[ib * EC_SECRET_SIZE], EC_SECRET_SIZE, bnS))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; // bnC is from last round (ib) if (!EC_POINT_oct2point(ecGrp, ptPk, &pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnCtx)) { LogPrintf("%s: EC_POINT_oct2point failed.\n", __func__); rv = 1; goto End; }; // ptT1 = s_{j+1}*G+c_{j+1}*P_{j+1} if (!EC_POINT_mul(ecGrp, ptT1, bnS, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; //s_{j+1}*H(P_{j+1})+c_{j+1}*I_j if (hashToEC(&pPubkeys[ib * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT2, ptT2) != 0) { LogPrintf("%s: hashToEC failed.\n", __func__); rv = 1; goto End; }; // ptT3 = s_{j+1}*H(P_{j+1}) if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT4 = c_{j+1}*I_j if (!EC_POINT_mul(ecGrp, ptT4, NULL, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; // ptT2 = ptT3 + ptT4 if (!EC_POINT_add(ecGrp, ptT2, ptT3, ptT4, bnCtx)) { LogPrintf("%s: EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; if ( !(EC_POINT_point2oct(ecGrp, ptT1, POINT_CONVERSION_COMPRESSED, &tempData[0], 33, bnCtx) == (int) EC_COMPRESSED_SIZE) || !(EC_POINT_point2oct(ecGrp, ptT2, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE)) { LogPrintf("%s: extract ptL and ptR failed.\n", __func__); rv = 1; goto End; }; CHashWriter ssCHash(SER_GETHASH, PROTOCOL_VERSION); ssCHash.write((const char*)tmpPkHash.begin(), 32); ssCHash.write((const char*)&tempData[0], 66); tmpHash = ssCHash.GetHash(); if (!bnC || !(BN_bin2bn(tmpHash.begin(), EC_SECRET_SIZE, bnC)) // bnC lags i by 1 || !BN_mod(bnC, bnC, bnOrder, bnCtx)) { LogPrintf("%s: hash -> bnC failed.\n", __func__); rv = 1; goto End; }; if (i == nSecretOffset && !BN_copy(bnCj, bnC)) { LogPrintf("%s: BN_copy failed.\n", __func__); rv = 1; goto End; }; if (i == 0) { memset(tempData, 0, EC_SECRET_SIZE); if ((nBytes = BN_num_bytes(bnC)) > (int) EC_SECRET_SIZE || BN_bn2bin(bnC, &tempData[0 + (EC_SECRET_SIZE-nBytes)]) != nBytes) { LogPrintf("%s: bnC -> sigC failed.\n", __func__); rv = 1; goto End; }; try { sigC.resize(32); } catch (std::exception& e) { LogPrintf("%s: sigC.resize failed.\n", __func__); rv = 1; goto End; }; memcpy(&sigC[0], tempData, EC_SECRET_SIZE); }; }; End: EC_POINT_free(ptKi); EC_POINT_free(ptPk); EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); EC_POINT_free(ptT4); BN_CTX_end(bnCtx); return rv; };