Constructing a P2WSH address from the BIP173 spec The BIP173 specification defines how to create Bech32 Segwit native addresses.

In the examples section a public key is given: 0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798. 

Based on that key it is somewhat easy to generate a P2WPKH address, one hashes the key with SHA256, then with RIPEMD160 and use the hex decoded result as the witness program (first two commands are simple CLI and the last is from the Dart bech32 library):

$ echo 0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 | xxd -r -p | openssl sha256
(stdin)= 0f715baf5d4c2ed329785cef29e562f73488c8a2bb9dbc5700b361d54b9b0554                                                                                                                                                                                                                                      

$ echo 0f715baf5d4c2ed329785cef29e562f73488c8a2bb9dbc5700b361d54b9b0554 | xxd -r -p | openssl ripemd160                                                                                                                                                         
(stdin)= 751e76e8199196d454941c45d1b3a323f1433bd

Segwit('bc', 0, HEX.decode("751e76e8199196d454941c45d1b3a323f1433bd"))
// bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3


Generating a P2WSH involves the script key OP_CHECKSIG followed by once SHA256 hashing. I'm at a loss how to construct said script. The opcode OP_CHECKSIG is encoded as 0xac. But appending that to the key seems silly (and doesn't work). Besides the CHECKSIG opcode requires two parameters. What do I hash?
First of all, what are you trying to do? Why do you need a P2WSH address?

A P2WSH address (and P2SH addresses earlier) send coins to a script, which requires satisfying that script to decode. A script of the form &lt;key&gt; CHECKSIG is wasteful - you should be using P2WPKH instead. In general, you use P2WSH when you have more complex spending requirements than a single key. This most often happens when you need multisig (multiple devices or people need to sign off on a spend).

Now, all of this is outside of the scope of BIP173, which only specifies how to encode segwit outputs into human-readable strings and back.

A segwit output is an output whose scriptPubKey starts with OP_0, OP_1, ..., OP_16, and is followed by a push of 2 to 40 bytes. That's it, and BIP173 can encode any of those.

Now, since the activation of BIP141 in Bitcoin, a small subset of segwit outputs have been given a meaning:


OP_0 + 20-byte push of RIPEMD160(SHA256(pubkey)) is called a P2WPKH for that public key.
OP_0 + 32-byte push of SHA256(script) is called P2WSH for that script.


All other kinds of segwit outputs are meaningless right now (non-standard and spendable by anyone), but that could change in the future. However, all of them can be encoded in Bech32 using BIP173. It doesn't care what the context or meaning is; it just encodes the version number (the OP_n opcode at the start) and the data bytes (what is being pushed afterwards).

Perhaps your confusion comes from the fact that the BIP173 test vectors use "key + OP_CHECKSIG" in its examples. That was just a simple way of constructing examples that are reproducible. They're not representative for how to actually use it.