Field-test results:
Using bitcointools and hashlib in Python. First, generate a normal native segwit address and its private key wif from a (very not cryptographically safe) private key:
bitcoinutils.setup.setup('testnet')
privkey_hex = "1234123412341234123412341234123412341234123412341234123412341234"
privkey_wif = bitcoinutils.keys.PrivateKey.from_bytes(bytes.fromhex(privkey_hex)).to_wif()
pubkey = bitcoinutils.keys.PrivateKey.from_bytes(bytes.fromhex(privkey_hex)).get_public_key().to_hex()
pubaddr = bitcoinutils.keys.PrivateKey.from_bytes(bytes.fromhex(privkey_hex)).get_public_key().get_segwit_address().to_string()
print(privkey_hex)
print(privkey_wif)
print(pubkey)
print(pubaddr)
The output is benign and as expected - our native segwit address on the last row:
1234123412341234123412341234123412341234123412341234123412341234
cNC5yqKCukH9sm5opMizA9Q2Q7P1KUy6vKfxHCmq88d3RLeZcPxh
02b4b003aebb5672a4c4dbc37da21f0255f9034109b6f5bf26ddb95b7ed6ff24f8
tb1qlk2s76mvtpf2rqrpm97ngk3skgjdw7jtz50lw8
Now, to verify the public address is the same, using a more "manual and hashing it yourself" approach:
def pubkey_to_hash160(pubkey):
if len(pubkey) == 130 or len(pubkey) == 66 and int(pubkey, 16):
return hashlib.new('ripemd160', bytes(hashlib.sha256(bytes.fromhex(pubkey)).digest())).hexdigest()
hash160 = pubkey_to_hash160(pubkey)
print(bitcoinutils.bech32.encode('tb',0,memoryview(bytes.fromhex(hash160)).tolist()))
It produces the identical public address -
tb1qlk2s76mvtpf2rqrpm97ngk3skgjdw7jtz50lw8 - confirming our code should be OK.
Now, to generate the non-standard "P2WPKH(Bech32m/v1)", the topic of this thread, simply change witness program 0 to 1:
print(bitcoinutils.bech32.encode('tb',1,memoryview(bytes.fromhex(hash160)).tolist()))
It yields
tb1plk2s76mvtpf2rqrpm97ngk3skgjdw7jtukgcxw - for which we supposedly have the private and public keys.
What's interesting is that Bitcoin Core and Electrum accept this as a legitimate receiving address. 0.001 tBTC was sent to it, and
the transaction was swiftly confirmed. Interestingly, this blockchain explorer prints out the "tb1p..." address correctly but also calls the type "Unknown."
Anyways, the big question: how about spending from it? No wallet software or semi-automatic online service (such as coinb.dev for P2SH) I am aware of can create raw transactions from segwit outputs, so I went with good old Notepad++ (and a little script to flip endianness for the tx hash)
and I decided to go with this:
020000000001013715989bfedc450192588c193465473d472fad620d6aea1768341af4aa2c49c10000000000fdffffff01318601000000000017a914628cde58e1bcd42efb72b1821ec9fdf49e0f1d49870120b4b003aebb5672a4c4dbc37da21f0255f9034109b6f5bf26ddb95b7ed6ff24f800000000
Because of the comments above, I had reasons to believe the output is either eternally stuck OR spendable by all, so I only used the public key serialized as the witness program (i.e., I didn't bother to sign with the private key). I ran it through Blockcypher's decode raw transaction service to verify that the serialization checks out and makes sense, which it does.
Now, onto actually broadcasting it. Uh-oh. Problemas.
Bitcoin Core console, sendrawtransaction: "bad-txns-nonstandard-inputs (code -26)"
Electrum console, broadcast(): "TxBroadcastServerReturnedError: Witness version reserved for soft-fork upgrades"
I was, however, able to broadcast it using Blockcypher's web service: "Transaction Successfully Broadcast" (the
tx here, but I think it will drop out of the mempool and disappear within hours).
At this moment, Blockcypher says, "Confidence low: 29%", and it hasn't reached the mempool of my take-back Electrum wallet, so unless someone else has a brilliant idea of how to spend it, it is stuck, barring a miracle (such as a future soft fork that allows this address format).
BUT! Isn't it strange that major wallet software allows sending to this homemade address type if outputs to such are forever unspendable?