Reputation: 1
I'm trying to generate Bitcoin testnet addresses in ruby by using this guide:
https://bhelx.simst.im/articles/generating-bitcoin-keys-from-scratch-with-ruby/
Here's the class I'm using:
require 'openssl'
require 'ecdsa'
require 'securerandom'
require 'base58'
class BitcoinAddressGenerator
ADDRESS_VERSION = '6f'
def self.generate_address
# Bitcoin uses the secp256k1 curve
curve = OpenSSL::PKey::EC.new('secp256k1')
# Now we generate the public and private key together
curve.generate_key
private_key_hex = curve.private_key.to_s(16)
puts "private_key_hex: #{private_key_hex}"
public_key_hex = curve.public_key.to_bn.to_s(16)
puts "public_key_hex: #{public_key_hex}"
pub_key_hash = public_key_hash(public_key_hex)
puts "pub_key_hash: #{pub_key_hash}"
address = generate_address_from_public_key_hash(public_key_hash(public_key_hex))
puts "address: #{address}"
end
def self.generate_address_from_public_key_hash(pub_key_hash)
pk = ADDRESS_VERSION + pub_key_hash
encode_base58(pk + checksum(pk))
end
def self.int_to_base58(int_val, leading_zero_bytes=0)
alpha = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
base58_val, base = '', alpha.size
while int_val > 0
int_val, remainder = int_val.divmod(base)
base58_val = alpha[remainder] + base58_val
end
base58_val
end
def self.encode_base58(hex)
leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
("1"*leading_zero_bytes) + int_to_base58( hex.to_i(16) )
end
def self.checksum(hex)
sha256(sha256(hex))[0...8]
end
# RIPEMD-160 (160 bit) hash
def self.rmd160(hex)
Digest::RMD160.hexdigest([hex].pack("H*"))
end
def self.sha256(hex)
Digest::SHA256.hexdigest([hex].pack("H*"))
end
# Turns public key into the 160 bit public key hash
def self.public_key_hash(hex)
rmd160(sha256(hex))
end
end
If I plug this address into blockchain.info and similar tools it says that it's an invalid address.
Any help would be greatly appreciated.
Upvotes: -1
Views: 114
Reputation: 27747
Hi and welcome to Stack Overflow.
I'm assuming that the code you've written above is the exact code you're using.
If so, the problem is that the last line of your method is the puts
, and the last line of the method is what is being returned by your method.
So your method is outputting a string something like: Address: ADDRESS_HERE
and what you need is to actually return the address.
To fix, change the last lines of your method to:
address = generate_address_from_public_key_hash(public_key_hash(public_key_hex))
puts "address: #{address}"
address
end
Upvotes: 0
Reputation: 1
it looks like there's a mistake in the generate_address_from_public_key_hash method. Instead of using pub_key_hash to generate the base58-encoded address, it should use pk. Here's the corrected code:
def self.generate_address_from_public_key_hash(pub_key_hash)
pk = ADDRESS_VERSION + pub_key_hash
encode_base58(pk + checksum(pk))
end
With these changes, the addresses generated by the generate_address method should be valid testnet addresses.
Upvotes: 0