mcdallas / cryptotools

MIT License
206 stars 80 forks source link

P2WSH and P2WPKH_P2SH etc? #27

Closed lattice0 closed 3 years ago

lattice0 commented 3 years ago

besides existing on the code, I cannot use P2WSH or P2WPKH_P2SH or etc, like:

print("P2WSH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2WSH'))

so I can generate addresses starting with 3.

Error:

Traceback (most recent call last):
  File "verify.py", line 31, in <module>
    print_addresses(xprv, count)
  File "verify.py", line 21, in print_addresses
    print("P2WSH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2WSH'))
  File "/home/lz/cryptotools/cryptotools/BTC/HD/bip32.py", line 191, in address
    return self.key.to_public().to_address(addresstype or self.type.value, compressed=True)
  File "/home/lz/cryptotools/cryptotools/ECDSA/secp256k1.py", line 143, in to_address
    return pubkey_to_address(self, addrtype)
  File "/home/lz/cryptotools/cryptotools/BTC/address.py", line 73, in pubkey_to_address
    converter = key_to_addr_versions[ADDRESS(version.upper())]
KeyError: <ADDRESS.P2WSH: 'P2WSH'>
lattice0 commented 3 years ago

Also tried with BIP49:

print("P2WSH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WSH'))

but same error

mcdallas commented 3 years ago

For BIP49 you want to use P2WPKH-P2SH as an address type

You can’t generate P2WSH, P2SH or P2WSH-P2SH addresses from a public key, those require a script as the name suggests

lattice0 commented 3 years ago

Is it possible to generate them from an Xprv or xpub?

xprv = Xprv.from_mnemonic(seed)
xpub = xprv.to_xpub()
print(xprv.to_xpub.to_address('P2WPKH'))
print(xpub.to_address('P2WPKH'))

dit not work

lattice0 commented 3 years ago

I'm trying to generate all possible addresses that the coldcard generates. I used:

def print_addresses(key, max_count):
    for x in range(max_count):
        print("P2PKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2PKH')) #appears on coldcard
        print("P2WPKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2WPKH'))
        print("P2PKH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2PKH'))
        print("P2WPKH:  m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH-P2SH')) #appears 

on coldcard

but only

P2PKH: m/44./0./0./0/0 P2WPKH-P2SH: m/49'/0'/0'/0/0

matched, there are still 2 sets of addresses that are not covered in this and I don't know. one set starts with bc... and the other 1. Do you know which type are they and how to generate from the seed + passphrase?

lattice0 commented 3 years ago

Ok, turns out this:

def print_addresses(key, max_count):
    for x in range(max_count):
        print("P2PKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/49./0./0./0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH-P2SH'))
        print("P2PKH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH-P2SH'))
        print("P2PKH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2WPKH-P2SH'))

generates the 3 sets, except the first set of addresses, for which I don't know how to generate. Do you have an idea? Also feel free to put these in the readme if you want to.

mcdallas commented 3 years ago

BIP44 —> P2PKH BIP49 —> P2WPKH-P2SH BIP84 —> P2WPKH

lattice0 commented 3 years ago
def print_addresses(key, max_count):
    for x in range(max_count):
        print("P2PKH: m/0/"+str(x)+": " + (key/0/x).address('P2PKH'))
        print("P2WPKH: m/0/"+str(x)+": " + (key/0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/0/"+str(x)+": " + (key/0/x).address('P2WPKH-P2SH'))

        print("P2PKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/44./0./0./0/"+str(x)+": " + (key/44./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/49./0./0./0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH-P2SH'))
        print("P2PKH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/49'/0'/0'/0/"+str(x)+": " + (key/49./0./0./0/x).address('P2WPKH-P2SH'))
        print("P2PKH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2PKH'))
        print("P2WPKH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2WPKH'))
        print("P2WPKH-P2SH: m/84'/0'/0'/0/"+str(x)+": " + (key/84./0./0./0/x).address('P2WPKH-P2SH'))

all of these appear on the coldcard now, thanks. The one missing was m/0/x