Skip to content

Instantly share code, notes, and snippets.

@nmarley
Last active August 9, 2017 17:20
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nmarley/506a3d3036d55c878696 to your computer and use it in GitHub Desktop.
Save nmarley/506a3d3036d55c878696 to your computer and use it in GitHub Desktop.
Convert Dash BIP32 extended public key version prefix from 'xpub' to 'drkv'
#! /usr/bin/env ruby
# Utility converting BIP32 extended key version bytes
require './dashutil'
xkey = ARGV.shift
pref = ARGV.shift
# xpub661MyMwAqRbcFnEEbFf8idiyo8QGKiqhTujUmaJsDhAEZ82cEQPMq69Y4V27vGc5rJnxsd26kyHpBJDW72YMjntsmASbdBy1awfGMsUvLCa
puts DashUtil.swap_prefix(xkey, pref)
#! /usr/bin/env ruby
# Example of converting Dash BIP32 extended public key (incorrectly) beginning
# with 'xpub' to correct prefix 'drkv'.
#
require 'bitcoin'
# test extended pub key
xpub = 'xpub661MyMwAqRbcF3jZGiw3QBt7nD13a7k8jVt9me27BL1vSeSpviDj6udJ5cnFyr2q2ofw7kMKGUepVhVsbLVsckxGzDmvnpGPr88CJAz1Ab5'
# Dash extended public key prefix
drkv_prefix = '02fe52f8'
# decode base58 pubkey
bin = Bitcoin.decode_base58(xpub)
# replace 4-byte version prefix
bin[0..7] = drkv_prefix
version = bin[0..7] # 0488b21e
depth = bin[8..9] # 00
parent_fingerprint = bin[10..17] # 00000000
child = bin[18..25] # 00000000
chain_code = bin[26..89] # 32bdad605aae059ae99303a1b74c8492630a0bf9f3b45680dfe82b03f8174365
key_data = bin[90..155] # 03906d7e79f8b55ce4d7720bbd478dff3f11f832459d2890e2c8fb2b3316e18455
# checksum...
# b43167ec
puts "version: #{version}"
puts "depth: #{depth}"
puts "parent_fingerprint: #{parent_fingerprint}"
puts "child: #{child}"
puts "chain_code: #{chain_code}"
puts "key_data: #{key_data}"
# add the checksum to the 78-byte xkey
drkbin = bin[0..155] + Bitcoin.checksum(bin[0..155])
# base58 encode again
drk = Bitcoin.encode_base58(drkbin)
# result has proper 'drkv' prefix and generates same addresses
puts drk
# => drkvjJe5sJgqomjLnD39LKGdme64zzL4d38fDEhkveYsjvqDZzEZSoq6VEE5znetSRvSB6pYAxhTViXJdZ5QygKogD4nsa31hQ8aVuW6psczteC
# Dash BIP32 utilities
require 'bitcoin'
require 'byebug'
require 'pp'
class DashUtil
VERSION_BYTES = {
'drkv' => '02fe52f8',
'drkp' => '02fe52cc',
'DRKV' => '3a8061a0',
'DRKP' => '3a805837',
'xpub' => '0488b21e',
'xprv' => '0488ade4',
'tpub' => '043587cf',
'tprv' => '04358394',
}
def self.swap_version_bytes(xkey, version_bytes)
hex = Bitcoin.decode_base58(xkey)
hex[0..7] = version_bytes
hex = hex[0..155] + Bitcoin.checksum(hex[0..155])
new_xkey = Bitcoin.encode_base58(hex)
return new_xkey
end
def self.swap_prefix(xkey, prefix)
swap_version_bytes(xkey, VERSION_BYTES[prefix])
rescue StandardError => ex
throw ex
end
end
#! /usr/bin/env ruby
# Utility converting BIP32 extended key version bytes
require 'dashruby'
require 'dashruby/extensions'
require './dashutil'
def gen_electrum_public_keys(xkey, type = :receive, num = 10)
path_prefix = (:change == type) ? "1" : "0"
# TODO: validation, also parsing pub/priv, etc.
if !xkey.match(/^drk[pv]/)
# TODO: determine prefix based on pub/priv key data (not version bytes)
# this assumes public key, which is a bad assumption.
xkey = DashUtil.swap_prefix(xkey, 'drkv')
end
public_keys = []
kc = Dash::Keychain.new(extended_key: xkey)
(0..(num-1)).each do |n|
path = "#{path_prefix}/#{n}"
pubkey = kc.derived_key(path).public_key.to_hex
public_keys.push( pubkey )
end
return public_keys
end
xkey = ARGV.shift
type = ARGV.shift || 'receive'
num = ARGV.shift || '5'
type = type.to_sym
num = num.to_i || 5
print "\n\n"
gen_electrum_public_keys(xkey, type, num).each do |pubkey|
puts pubkey
end
# original incorrect 'xpub' key:
xpub661MyMwAqRbcF3jZGiw3QBt7nD13a7k8jVt9me27BL1vSeSpviDj6udJ5cnFyr2q2ofw7kMKGUepVhVsbLVsckxGzDmvnpGPr88CJAz1Ab5
# First two receiving addresses generated by Electrum:
XfodG6PGyXksxznJXzKFPgU1q9QdPBNYB2
Xb4AKDUJBkjUSYVzuMXxLAxkUJaWomozGT
# ----------------------------------------------------------------------
# correctly convert 'drkv' key:
drkvjJe5sJgqomjLnD39LKGdme64zzL4d38fDEhkveYsjvqDZzEZSoq6VEE5znetSRvSB6pYAxhTViXJdZ5QygKogD4nsa31hQ8aVuW6psczteC
# First two receiving addresses generated by Electrum:
XfodG6PGyXksxznJXzKFPgU1q9QdPBNYB2
Xb4AKDUJBkjUSYVzuMXxLAxkUJaWomozGT
#! /usr/bin/env ruby
require 'dashruby'
require 'dashruby/extensions'
# test extended pub key
xkey = 'drkvjJe5sJgqomjLnwXpeqzj65vw1ujHNeEDweZ5vaqdnHyXgTpLkVzjDQkKyetkNrVgzbwZvqNEzDAJK9o3VNNHoF1PeWhgXmqCEj3AtcMrX1c'
path = '0/0'
kc = Dash::Keychain.new(extended_key: xkey)
derived = kc.derived_key(path)
pubkey = derived.public_key.to_hex
addr = derived.address.to_s
puts " Path: m/#{path}"
puts "Public Key: #{pubkey}"
puts " Address: #{addr}"
print "\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment