Author

Topic: Would P2WPKH v1/bech32m addressee be legal (and usable and spendable)? (Read 113 times)

copper member
Activity: 193
Merit: 234
Click "+Merit" top-right corner
Oh, I just realized you can test beyond v1. Said and done:

Code:
bitcoinutils.bech32.encode('tb', 2, memoryview(bytes.fromhex(hash160)).tolist())
bitcoinutils.bech32.encode('tb', 3, memoryview(bytes.fromhex(hash160)).tolist())
bitcoinutils.bech32.encode('tb', 4, memoryview(bytes.fromhex(hash160)).tolist())
bitcoinutils.bech32.encode('tb', 5, memoryview(bytes.fromhex(hash160)).tolist())

--->

tb1zlk2s76mvtpf2rqrpm97ngk3skgjdw7jtpac93n
tb1rlk2s76mvtpf2rqrpm97ngk3skgjdw7jt2r0wuc
tb1ylk2s76mvtpf2rqrpm97ngk3skgjdw7jtjt3kkq
tb19lk2s76mvtpf2rqrpm97ngk3skgjdw7jte4xamt

One single transaction to these nonsense addresses was accepted and confirmed without a glitch...

What have we learned here? That major wallet software gives you no warnings before sending to address types that haven't yet been defined. And that is, in my opinion, suboptimal. Wallet software should give you a "please note that you are sending funds to undefined address types, and your funds will be lost" notice.
legendary
Activity: 3430
Merit: 10505
Code:
020000000001013715989bfedc450192588c193465473d472fad620d6aea1768341af4aa2c49c10000000000fdffffff01318601000000000017a914628cde58e1bcd42efb72b1821ec9fdf49e0f1d49870120

b4b003aebb5672a4c4dbc37da21f0255f9034109b6f5bf26ddb95b7ed6ff24f8

00000000
I don't think you needed to provide any witness at all (the part I separated) to spend this output. Which is what anyone-can-spend means.

Quote
Bitcoin Core console, sendrawtransaction: "bad-txns-nonstandard-inputs (code -26)"
Electrum console, broadcast(): "TxBroadcastServerReturnedError: Witness version reserved for soft-fork upgrades"
That's the non-standard error I mentioned above. Mempool rejects it but if you can bypass standard tests (like if it is already in a block) it is considered valid.

Quote
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).
You could spend some time trying to mine a block yourself if you want to have a record of it on a public blockchain.
Otherwise you could test all of this on RegTest.

Someone correct me if I'm wrong but Taproot is always active on RegTest. So just mine a 100 blocks in a second (100 because coinbase needs to mature to be spendable), send the output of your first coinbase to your bc1p address and mine another block. Then create this final tx spending that non-standard output and mine that block too.

Read some sources on how to work on RegTest like this one for more information: https://gist.github.com/System-Glitch/cb4e87bf1ae3fec9925725bb3ebe223a

Quote
BUT! Isn't it strange that major wallet software allows sending to this homemade address type if outputs to such are forever unspendable?
Such outputs are actually spendable by anyone until there is a consensus rule added to handle these things, then it would depend on whether you can provide the correct script to spend them.

The decision to accept the address may be because of having forward-compatibility (if some day a new version would be added, the old clients are still easy to use) although I'd say they should show a big warning that to this version of software you run and at that time the destination address you entered is non-standard and your funds could be lost.
copper member
Activity: 193
Merit: 234
Click "+Merit" top-right corner
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:

Code:
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:

Code:
1234123412341234123412341234123412341234123412341234123412341234
cNC5yqKCukH9sm5opMizA9Q2Q7P1KUy6vKfxHCmq88d3RLeZcPxh
02b4b003aebb5672a4c4dbc37da21f0255f9034109b6f5bf26ddb95b7ed6ff24f8
tb1qlk2s76mvtpf2rqrpm97ngk3skgjdw7jtz50lw8

Now, to verify the public address is the same, using a more "manual and hashing it yourself" approach:

Code:
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:

Code:
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:

Code:
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?








legendary
Activity: 2856
Merit: 7410
Crypto Swap Exchange
Quote
Will wallets accept it?
They should not since the address (the data part) is short and non-standard (20 byte instead of expected 32).

I just tried it on Electrum watch-only, where
1. 2nd address created by OP got accepted without any warning or error message.
2. Electrum also let me create unsigned TX with OP's 2nd address as receiver.
legendary
Activity: 3430
Merit: 10505
Good for anything?
It's good for burning your precious coins! .... or at least make it extremely difficult to be spent but spendable by anyone!!!

Quote
Will wallets accept it?
They should not since the address (the data part) is short and non-standard (20 byte instead of expected 32).

Quote
Will nodes propagate a transaction to it over the BTC network?
No because their IsStandardTx[1] check will recognize[2] such transactions as non-standard so they'll not propagate it.

[1] https://github.com/bitcoin/bitcoin/blob/dfc35c99340da3236e2841b348580f0e881762ce/src/policy/policy.cpp#L94
[2] https://github.com/bitcoin/bitcoin/blob/dfc35c99340da3236e2841b348580f0e881762ce/src/script/solver.cpp#L164

Quote
Can we use normal privkeys to spend from it with, as we do with regular native segwit?
Technically anybody should be able to spend any coins sent to such output. The reason is that witness program of any size other than 32 is valid but not-defined (also non-standard hence the burned coins as I said at first) so the node ignores verification of it expecting it to be a future change/soft-fork.

It falls into this branch: https://github.com/bitcoin/bitcoin/blob/dfc35c99340da3236e2841b348580f0e881762ce/src/script/interpreter.cpp#L1946-L1952
which will return true.

Quote
Due to lack of better terminology, we can call them P2WPKH(Bech32m). A thing or not? That's the question.
No because there is nothing like it defined in the consensus rules so the protocol sees it as an arbitrary hash not pubkey hash.
copper member
Activity: 193
Merit: 234
Click "+Merit" top-right corner
We have a public key. We have its RIPEMD(SHA256(pubkey)) hash, a.k.a. HASH160

We can easily construct a valid native segwit address by

Code:
> bitcoinutils.bech32.encode('bc',0,memoryview(bytes.fromhex(our_hash160)).tolist())
> bc1qmgt5t6d4fx7sh7s626vhr3m7hgcv6kjt450t6x

So far, nothing strange. Works as intended.

But if we change the version from 0 to 1 and disregard all taproot standards, we get a bech32m public address like so:

Code:
> bitcoinutils.bech32.encode('bc',1,memoryview(bytes.fromhex(our_hash160)).tolist())
> bc1pmgt5t6d4fx7sh7s626vhr3m7hgcv6kjttkgvj0

Good for anything? Will wallets accept it? Will nodes propagate a transaction to it over the BTC network? Can we use normal privkeys to spend from it with, as we do with regular native segwit?

Due to lack of better terminology, we can call them P2WPKH(Bech32m). A thing or not? That's the question.
.
Jump to: