BCW_API hd_public_key hd_public_key::generate_public_key(uint32_t i) const { if (!valid_) return hd_private_key(); if (first_hardened_key <= i) return hd_public_key(); data_chunk data; data.reserve(33 + 4); extend_data(data, K_); extend_data(data, to_big_endian(i)); auto I = split(hmac_sha512_hash(data, to_data_chunk(c_))); // The returned child key Ki is point(parse256(IL)) + Kpar. ec_point Ki = K_; if (!ec_tweak_add(Ki, I.L)) return hd_public_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_public_key(Ki, I.R, lineage); }
BCW_API hd_private_key hd_private_key::generate_private_key(uint32_t i) const { if (!valid_) return hd_private_key(); data_chunk data; data.reserve(33 + 4); if (first_hardened_key <= i) { data.push_back(0x00); extend_data(data, k_); extend_data(data, to_big_endian(i)); } else { extend_data(data, K_); extend_data(data, to_big_endian(i)); } auto I = split(hmac_sha512_hash(data, to_data_chunk(c_))); // The child key ki is (parse256(IL) + kpar) mod n: ec_secret ki = k_; if (!ec_add(ki, I.L)) return hd_private_key(); hd_key_lineage lineage { lineage_.testnet, static_cast<uint8_t>(lineage_.depth + 1), fingerprint(), i }; return hd_private_key(ki, I.R, lineage); }
data_chunk deterministic_wallet::generate_public_key( size_t n, bool for_change) const { hash_digest sequence = get_sequence(n, for_change); ssl_bignum x, y, z; BN_bin2bn(sequence.data(), sequence.size(), z); BN_bin2bn(master_public_key_.data(), 32, x); BN_bin2bn(master_public_key_.data() + 32, 32, y); // Create a point. ec_group group(EC_GROUP_new_by_curve_name(NID_secp256k1)); ec_point mpk(EC_POINT_new(group)); bn_ctx ctx(BN_CTX_new()); EC_POINT_set_affine_coordinates_GFp(group, mpk, x, y, ctx); ec_point result(EC_POINT_new(group)); // result pubkey_point = mpk_pubkey_point + z*curve.generator ssl_bignum one; BN_one(one); EC_POINT_mul(group, result, z, mpk, one, ctx); // Create the actual public key. EC_POINT_get_affine_coordinates_GFp(group, result, x, y, ctx); // 04 + x + y data_chunk raw_pubkey{0x04}; extend_data(raw_pubkey, bignum_data(x)); extend_data(raw_pubkey, bignum_data(y)); return raw_pubkey; }
hash_digest deterministic_wallet::get_sequence(size_t n, bool for_change) { data_chunk chunk; extend_data(chunk, std::to_string(n)); chunk.push_back(':'); chunk.push_back(for_change ? '1' : '0'); chunk.push_back(':'); extend_data(chunk, master_public_key_); hash_digest result = generate_sha256_hash(chunk); std::reverse(result.begin(), result.end()); return result; }
std::string payment_address::encoded(uint8_t version_byte) const { data_chunk unencoded_address; BITCOIN_ASSERT( type_ == payment_type::pubkey_hash || type_ == payment_type::script_hash); // Type, Hash, Checksum doth make thy address unencoded_address.push_back(version_byte); extend_data(unencoded_address, hash_); uint32_t checksum = generate_sha256_checksum(unencoded_address); extend_data(unencoded_address, uncast_type(checksum)); BITCOIN_ASSERT(unencoded_address.size() == 25); return encode_base58(unencoded_address); }
data_chunk wrap(uint8_t version, data_slice payload) { data_chunk wrapped; wrapped.push_back(version); extend_data(wrapped, payload); append_checksum(wrapped); return wrapped; }
BCW_API std::string hd_public_key::serialize() const { data_chunk data; data.reserve(serialized_length); auto prefix = mainnet_public_prefix; if (lineage_.testnet) prefix = testnet_public_prefix; extend_data(data, to_big_endian(prefix)); data.push_back(lineage_.depth); extend_data(data, to_little_endian(lineage_.parent_fingerprint)); extend_data(data, to_big_endian(lineage_.child_number)); extend_data(data, c_); extend_data(data, K_); append_checksum(data); return encode_base58(data); }
hash_digest hash_transaction_impl(const transaction_type& tx, uint32_t* hash_type_code) { data_chunk serialized_tx(satoshi_raw_size(tx)); satoshi_save(tx, serialized_tx.begin()); if (hash_type_code != nullptr) extend_data(serialized_tx, to_little_endian(*hash_type_code)); return bitcoin_hash(serialized_tx); }
hash_digest hash_transaction_impl(const message::transaction& tx, uint32_t* hash_type_code) { data_chunk serialized_tx(satoshi_raw_size(tx)); satoshi_save(tx, serialized_tx.begin()); if (hash_type_code != nullptr) extend_data(serialized_tx, uncast_type(*hash_type_code)); return generate_sha256_hash(serialized_tx); }
std::string payment_address::encoded() const { data_chunk unencoded_address; unencoded_address.reserve(25); // Type, Hash, Checksum doth make thy address unencoded_address.push_back(version_); extend_data(unencoded_address, hash_); append_checksum(unencoded_address); BITCOIN_ASSERT(unencoded_address.size() == 25); return encode_base58(unencoded_address); }
data_chunk save_script(const script& scr) { data_chunk raw_script; for (operation op: scr.operations()) { byte raw_byte = static_cast<byte>(op.code); if (op.code == opcode::special) raw_byte = op.data.size(); raw_script.push_back(raw_byte); extend_data(raw_script, op.data); } return raw_script; }
std::string stealth_address::encoded() const { if (!valid_) return std::string(); data_chunk raw_address; raw_address.push_back(get_version()); raw_address.push_back(get_options()); extend_data(raw_address, scan_pubkey_); // Spend_pubkeys must be guarded against a size greater than 255. auto number_spend_pubkeys = static_cast<uint8_t>(spend_pubkeys_.size()); // Adjust for key reuse. if (get_reuse_key()) --number_spend_pubkeys; raw_address.push_back(number_spend_pubkeys); // Serialize the spend keys, excluding any that match the scan key. for (const ec_point& pubkey: spend_pubkeys_) if (pubkey != scan_pubkey_) extend_data(raw_address, pubkey); raw_address.push_back(signatures_); // The prefix must be guarded against a size greater than 32 // so that the bitfield can convert into uint32_t and sized by uint8_t. auto prefix_number_bits = static_cast<uint8_t>(prefix_.size()); // Serialize the prefix bytes/blocks. raw_address.push_back(prefix_number_bits); extend_data(raw_address, prefix_.blocks()); append_checksum(raw_address); return encode_base58(raw_address); }
data_chunk create_raw_message(const Message& packet) { data_chunk payload(satoshi_raw_size(packet)); satoshi_save(packet, payload.begin()); // Make the header packet and serialise it message::header head; head.magic = magic_value; head.command = satoshi_command(packet); head.payload_length = payload.size(); head.checksum = generate_sha256_checksum(payload); data_chunk raw_header(satoshi_raw_size(head)); satoshi_save(head, raw_header.begin()); // Construct completed packet with header + payload data_chunk whole_message = raw_header; extend_data(whole_message, payload); // Probably not the right place for this // Networking output in an exporter log_info(log_domain::network) << "s: " << head.command << " (" << payload.size() << " bytes)"; return whole_message; }
data_chunk create_raw_message(const Message& packet) { data_chunk payload(satoshi_raw_size(packet)); satoshi_save(packet, payload.begin()); // Make the header packet and serialise it header_type head; head.magic = magic_value(); head.command = satoshi_command(packet); head.payload_length = static_cast<uint32_t>(payload.size()); head.checksum = bitcoin_checksum(payload); data_chunk raw_header(satoshi_raw_size(head)); satoshi_save(head, raw_header.begin()); // Construct completed packet with header + payload data_chunk whole_message = raw_header; extend_data(whole_message, payload); // Probably not the right place for this // Networking output in an exporter log_debug(LOG_NETWORK) << "s: " << head.command << " (" << payload.size() << " bytes)"; return whole_message; }
void readable_data_type::set(const std::string& data) { extend_data(data_buffer_, data); prepare(); }
void readable_data_type::set(const short_hash& data) { extend_data(data_buffer_, data); prepare(); }
void readable_data_type::set(const hash_digest& data) { extend_data(data_buffer_, data); prepare(); }
void readable_data_type::set(const data_chunk& data) { extend_data(data_buffer_, data); prepare(); }
void append_checksum(data_chunk& data) { const auto checksum = bitcoin_checksum(data); extend_data(data, to_little_endian(checksum)); }
hash_digest transaction::hash(uint32_t sighash_type) const { auto serialized = to_data(); extend_data(serialized, to_little_endian(sighash_type)); return bitcoin_hash(serialized); }
BC_API void append_checksum(data_chunk& data) { uint32_t checksum = bitcoin_checksum(data); extend_data(data, to_little_endian(checksum)); }
hash_digest transaction::hash(uint32_t hash_type_code) const { data_chunk serialized = to_data(); extend_data(serialized, to_little_endian(hash_type_code)); return bitcoin_hash(serialized); }