Saving money on bitcoin transaction fees with segregated witness first requires you to receive bitcoin in the form of segwit utxos. This post will go over a libbitcoin script for generating a testnet P2SH-P2WKH address to send your bitcoins to and have them ready for spending in segwit transactions.
In order to begin spending bitcoins via segregated witness transactions you need receive pay-to-witness-key-hash outputs. So, the first thing you need to create is a witness program that consist of a version number 0 and compressed hash of your public key.
One thing we need to be sure of is that we always use a compressed public key to generate a P2WKH address. So, first I define a function for getting the compressed public key from a mnemonic by decoding it to its seed and then calling the point getter to get the ec compressed public key.
ec_compressed getPublicKey()
{
std::string mnemonic = "portion shop border uniform loan grab dismiss boss wild magnet strong supreme era swing else keep voyage forest";
data_chunk seed = to_chunk(decode_mnemonic(split(mnemonic)));
hd_private privateKey = hd_private(seed, hd_private::testnet);
ec_compressed compressedPublicKey = privateKey.to_public().point();
return compressedPublicKey;
}
Then we need to define a function that will create a the P2WKH which simply looks like this:
0 [Compressed Public Key Hash]
To do this we need to create a bitcoin short hash of the compressed public key which we will pass as an argument. This short hash amounts to a RIPEMD160 hash of a SHA256 hash of the compressed public key point. We then return this key hash as a data chunk in an operations list prefixed with an opcode 0 object.
operation::list witnessProgram(ec_compressed publicKey)
{
short_hash KeyHash = bitcoin_short_hash(publicKey);
return {operation(opcode(0)), operation(to_chunk(KeyHash))};
}
Now we can create a script object for our witness program and print it out to the console.
int main()
{
//Output Compressed Public Key
std::cout << "Public Key: "<< encode_base16(getPublicKey()) << std::endl;
//Output Witness Program
script P2WPKH = script(witnessProgram(getPublicKey()));
std::cout << "Witness Program: " << P2WPKH.to_string(0) << std::endl;
}
Now in order to make these P2WPKH outputs payable by anyone regardless of their segwit awareness, we need to wrap them in a P2SH address. To do this we first save a short hash of the witness program and pass it to a P2SH script pattern factory.
int main()
{
//Output Compressed Public Key
std::cout << "Public Key: "<< encode_base16(getPublicKey()) << std::endl;
//Output Witness Program
script P2WPKH = script(witnessProgram(getPublicKey()));
std::cout << "Witness Program: " << P2WPKH.to_string(0) << std::endl;
//Create P2SH script
short_hash WitnessProgramHash = bitcoin_short_hash(P2WPKH.to_data(0));
script P2SH_P2WPKH = script::to_pay_script_hash_pattern(WitnessProgramHash);
}
Then we can print out the P2SH_P2WPKH script pubkey as a string to the console.
We can also print the payment address by passing the witness program script to the payment address object and calling the encoded accessor.
int main()
{
//Output Compressed Public Key
std::cout << "Public Key: "<< encode_base16(getPublicKey()) << std::endl;
//Output Witness Program
script P2WPKH = script(witnessProgram(getPublicKey()));
std::cout << "Witness Program: " << P2WPKH.to_string(0) << std::endl;
//Create P2SH script
short_hash WitnessProgramHash = bitcoin_short_hash(P2WPKH.to_data(0));
script P2SH_P2WPKH = script::to_pay_script_hash_pattern(WitnessProgramHash);
//Print our P2SH script and address
std::cout <<"P2SH Script: " <<P2SH_P2WPKH.to_string(0) << std::endl;
std::cout << "Payment Address: " <<payment_address(P2WPKH, payment_address::testnet_p2sh).encoded() << std::endl;
}
As usual this program can be compiled and run via the Command line:
$ g++ -std=c++11 -o segwit segwit.cpp $(pkg-config --cflags libbitcoin --libs libbitcoin) $ ./segwit
You’ll note that the payment address begins with a 2, this denotes a testnet Pay-To-Script-Hash address since segwit address can be paid to the same as P2SH. A mainnet segwit address with start with a 3.

Any testnet coins sent to this address will be ready to spend with a fee-discounted segwit transaction.