parent
a8fafbc6c0
commit
aa332a7008
@ -0,0 +1,40 @@
|
||||
#include <bitcoin/bitcoin.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Private secret key.
|
||||
bc::ec_secret secret = bc::decode_hash(
|
||||
"038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776");
|
||||
// Get public key.
|
||||
bc::ec_point public_key = bc::secret_to_public_key(secret);
|
||||
std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;
|
||||
|
||||
// Create Bitcoin address.
|
||||
// Normally you can use:
|
||||
// bc::payment_address payaddr;
|
||||
// bc::set_public_key(payaddr, public_key);
|
||||
// const std::string address = payaddr.encoded();
|
||||
|
||||
// Compute hash of public key for P2PKH address.
|
||||
const bc::short_hash hash = bc::bitcoin_short_hash(public_key);
|
||||
|
||||
bc::data_chunk unencoded_address;
|
||||
// Reserve 25 bytes
|
||||
// [ version:1 ]
|
||||
// [ hash:20 ]
|
||||
// [ checksum:4 ]
|
||||
unencoded_address.reserve(25);
|
||||
// Version byte, 0 is normal BTC address (P2PKH).
|
||||
unencoded_address.push_back(0);
|
||||
// Hash data
|
||||
bc::extend_data(unencoded_address, hash);
|
||||
// Checksum is computed by hashing data, and adding 4 bytes from hash.
|
||||
bc::append_checksum(unencoded_address);
|
||||
// Finally we must encode the result in Bitcoin's base58 encoding
|
||||
assert(unencoded_address.size() == 25);
|
||||
const std::string address = bc::encode_base58(unencoded_address);
|
||||
|
||||
std::cout << "Address: " << address << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
import ecdsa
|
||||
import random
|
||||
from ecdsa.util import string_to_number, number_to_string
|
||||
|
||||
# secp256k1, http://www.oid-info.com/get/1.3.132.0.10
|
||||
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
|
||||
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
|
||||
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
|
||||
_a = 0x0000000000000000000000000000000000000000000000000000000000000000L
|
||||
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
|
||||
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
|
||||
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
|
||||
generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
|
||||
oid_secp256k1 = (1, 3, 132, 0, 10)
|
||||
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1)
|
||||
ec_order = _r
|
||||
|
||||
curve = curve_secp256k1
|
||||
generator = generator_secp256k1
|
||||
|
||||
def random_secret():
|
||||
random_char = lambda: chr(random.randint(0, 255))
|
||||
convert_to_int = lambda array: int("".join(array).encode("hex"), 16)
|
||||
byte_array = [random_char() for i in range(32)]
|
||||
return convert_to_int(byte_array)
|
||||
|
||||
def get_point_pubkey(point):
|
||||
if point.y() & 1:
|
||||
key = '03' + '%064x' % point.x()
|
||||
else:
|
||||
key = '02' + '%064x' % point.x()
|
||||
return key.decode('hex')
|
||||
|
||||
def get_point_pubkey_uncompressed(point):
|
||||
key = '04' + \
|
||||
'%064x' % point.x() + \
|
||||
'%064x' % point.y()
|
||||
return key.decode('hex')
|
||||
|
||||
# Generate a new private key.
|
||||
secret = random_secret()
|
||||
print "Secret: ", secret
|
||||
|
||||
# Get the public key point.
|
||||
point = secret * generator
|
||||
print "EC point:", point
|
||||
|
||||
print "BTC public key:", get_point_pubkey(point).encode("hex")
|
||||
|
||||
# Given the point (x, y) we can create the object using:
|
||||
point1 = ecdsa.ellipticcurve.Point(curve, point.x(), point.y(), ec_order)
|
||||
assert point1 == point
|
||||
|
@ -0,0 +1,62 @@
|
||||
#include <bitcoin/bitcoin.hpp>
|
||||
|
||||
bc::hash_digest create_merkle(bc::hash_digest_list& merkle)
|
||||
{
|
||||
// Stop if hash list is empty.
|
||||
if (merkle.empty())
|
||||
return bc::null_hash;
|
||||
else if (merkle.size() == 1)
|
||||
return merkle[0];
|
||||
|
||||
// While there is more than 1 hash in the list, keep looping...
|
||||
while (merkle.size() > 1)
|
||||
{
|
||||
// If number of hashes is odd, duplicate last hash in the list.
|
||||
if (merkle.size() % 2 != 0)
|
||||
merkle.push_back(merkle.back());
|
||||
// List size is now even.
|
||||
assert(merkle.size() % 2 == 0);
|
||||
|
||||
// New hash list.
|
||||
bc::hash_digest_list new_merkle;
|
||||
// Loop through hashes 2 at a time.
|
||||
for (auto it = merkle.begin(); it != merkle.end(); it += 2)
|
||||
{
|
||||
// Join both current hashes together (concatenate).
|
||||
bc::data_chunk concat_data(bc::hash_size * 2);
|
||||
auto concat = bc::make_serializer(concat_data.begin());
|
||||
concat.write_hash(*it);
|
||||
concat.write_hash(*(it + 1));
|
||||
assert(concat.iterator() == concat_data.end());
|
||||
// Hash both of the hashes.
|
||||
bc::hash_digest new_root = bc::bitcoin_hash(concat_data);
|
||||
// Add this to the new list.
|
||||
new_merkle.push_back(new_root);
|
||||
}
|
||||
// This is the new list.
|
||||
merkle = new_merkle;
|
||||
|
||||
// DEBUG output -------------------------------------
|
||||
std::cout << "Current merkle hash list:" << std::endl;
|
||||
for (const auto& hash: merkle)
|
||||
std::cout << " " << bc::encode_hex(hash) << std::endl;
|
||||
std::cout << std::endl;
|
||||
// --------------------------------------------------
|
||||
}
|
||||
// Finally we end up with a single item.
|
||||
return merkle[0];
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Replace these hashes with ones from a block to reproduce the same merkle root.
|
||||
bc::hash_digest_list tx_hashes{{
|
||||
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000011"),
|
||||
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000022"),
|
||||
}};
|
||||
const bc::hash_digest merkle_root = create_merkle(tx_hashes);
|
||||
std::cout << "Result: " << bc::encode_hex(merkle_root) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
Display the genesis block message by Satoshi.
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <bitcoin/bitcoin.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Create genesis block.
|
||||
bc::block_type block = bc::genesis_block();
|
||||
// Genesis block contains a single coinbase transaction.
|
||||
assert(block.transactions.size() == 1);
|
||||
// Get first transaction in block (coinbase).
|
||||
const bc::transaction_type& coinbase_tx = block.transactions[0];
|
||||
// Coinbase tx has a single input.
|
||||
assert(coinbase_tx.inputs.size() == 1);
|
||||
const bc::transaction_input_type& coinbase_input = coinbase_tx.inputs[0];
|
||||
// Convert the input script to its raw format.
|
||||
const bc::data_chunk& raw_message = save_script(coinbase_input.script);
|
||||
// Convert this to an std::string.
|
||||
std::string message;
|
||||
message.resize(raw_message.size());
|
||||
std::copy(raw_message.begin(), raw_message.end(), message.begin());
|
||||
// Display the genesis block message.
|
||||
std::cout << message << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
#include <bitcoin/bitcoin.hpp>
|
||||
|
||||
// The string we are searching for
|
||||
const std::string search = "1kid";
|
||||
|
||||
// Generate a random secret key. A random 32 bytes.
|
||||
bc::ec_secret random_secret(std::default_random_engine& engine);
|
||||
// Extract the Bitcoin address from an EC secret.
|
||||
std::string bitcoin_address(const bc::ec_secret& secret);
|
||||
// Case insensitive comparison with the search string.
|
||||
bool match_found(const std::string& address);
|
||||
|
||||
int main()
|
||||
{
|
||||
std::random_device random;
|
||||
std::default_random_engine engine(random());
|
||||
// Loop continuously...
|
||||
while (true)
|
||||
{
|
||||
// Generate a random secret.
|
||||
bc::ec_secret secret = random_secret(engine);
|
||||
// Get the address.
|
||||
std::string address = bitcoin_address(secret);
|
||||
// Does it match our search string? (1kid)
|
||||
if (match_found(address))
|
||||
{
|
||||
// Success!
|
||||
std::cout << "Found vanity address! " << address << std::endl;
|
||||
std::cout << "Secret: " << bc::encode_hex(secret) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Should never reach here!
|
||||
return 0;
|
||||
}
|
||||
|
||||
bc::ec_secret random_secret(std::default_random_engine& engine)
|
||||
{
|
||||
// Create new secret...
|
||||
bc::ec_secret secret;
|
||||
// Iterate through every byte setting a random value...
|
||||
for (uint8_t& byte: secret)
|
||||
byte = engine() % std::numeric_limits<uint8_t>::max();
|
||||
// Return result.
|
||||
return secret;
|
||||
}
|
||||
|
||||
std::string bitcoin_address(const bc::ec_secret& secret)
|
||||
{
|
||||
// Convert secret to pubkey...
|
||||
bc::ec_point pubkey = bc::secret_to_public_key(secret);
|
||||
// Finally create address.
|
||||
bc::payment_address payaddr;
|
||||
bc::set_public_key(payaddr, pubkey);
|
||||
// Return encoded form.
|
||||
return payaddr.encoded();
|
||||
}
|
||||
|
||||
bool match_found(const std::string& address)
|
||||
{
|
||||
auto addr_it = address.begin();
|
||||
// Loop through the search string comparing it to the lower case
|
||||
// character of the supplied address.
|
||||
for (auto it = search.begin(); it != search.end(); ++it, ++addr_it)
|
||||
if (*it != std::tolower(*addr_it))
|
||||
return false;
|
||||
// Reached end of search string, so address matches.
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in new issue