segregated witness – generating a zprv from a base58 rootKey with bitcoinjs-lib

var bitcoin = require('bitcoinjs-lib');
let bip32 = require('bip32');

let rootKey = 'xprv9s21ZrQH143K32CfqoCQHtbKiEb5BqFazXX6jCtNCnuty3gUjxS4CsXWi9rcNyHdjDVPiC6P1bnyEZr2ioouRq56h6HAdwejeTty1BsSEtL'
const node = bip32.fromBase58(rootKey, bitcoin.networks.bitcoin);

//legacy account extended private key
console.log("LEGACY: " + node.derivePath("m/44'/0'/0").toBase58())
//xprv9y7nL2k2diLdA9bmop94K8Pec2WdL998PLdvTraxj5jiQ36gnLmhVJG4bY8FzgqZPaBM5HDBi9sgRK1ZCi14n5j4Pk1o6d3j4Y6T9NS4nA6
(works as expected)


//segwit account extended private key
//trying to get a segwit extended private key (zprv) using the same inputs as above.

I want to get a segwit/bech32 extended private key using the same root key as above. How can I do this using bitcoinjs-lib? BIP84 only works for mnemonics IIRC.

segregated witness – Why are P2WSH addresses larger than P2SH addresses?

Because P2SH addresses are too short to provide typically desirable levels of security security level we expect from Bitcoin, against certain attacks. On top of that, they use bech32 encoding rather than base58, which means they’re slightly longer for the same amount of data, but are case insensitive instead.

For any kind of “multi party” address (that is, an address constructed by multiple distinct and distrusting participants that each have their own key, such as multisig), a particular collision attack exists that has runtime O(2bits/2), where bits is the number of bits of entropy in the address.

P2PKH, P2WPKH, and P2SH addresses have 160-bit hashes in their addresses. For P2PKH and P2WPKH this is fine, as it only supports single-party construction. However, as P2SH supports multisig and other multi-party constructions, it means an ~280 attack is possible(*). Bitcoin typically has a 2128 security target for attacks, so this is insufficient. That doesn’t mean such a collision attack is practical – it’s just far weaker than what the rest of the system provides, and as computing performance increases it may become feasible for well-funded parties.

To address this, P2WSH introduced a multi-party-capable address that contains a 256-bit hash, so it has ~2128 collision security.

In the upcoming Taproot upgrade, a new P2TR address type is introduced. It has the same length as P2WSH addresses, and also contains ~256 bits of entropy. Due to the nature of Taproot, which merges P2PKH and P2SH style spending into one, this means even single-party addresses are 256 bits in it.

For details of the attack, see https://bitcoin.stackexchange.com/a/54847/208.

(*) There are ways to avoid the collision attack problem, even with short hashes. They significantly complicate address construction and spending however. So the choice to provide a 256-bit script hash mechanism is really just to make sure multi-party address construction isn’t needlessly complicated.

segregated witness – How hard is it for an exchange to adopt native segwit? Is it not as simple as updating the address regex checker on the front-end?

Stack Exchange Network


Stack Exchange network consists of 176 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Visit Stack Exchange

segregated witness – createPaymentTransactionNew with Bech32 address

How to properly call createPaymentTransactionNew using @ledgerhq/hw-app-bt to spend utxos from a bech32 transaction?

This is the code I’m using to call it, having previously defined inputs and purpose, coinPath, accountNumber:

tx = await appBtc.createPaymentTransactionNew({
                    inputs: inputs,
                    associatedKeysets: `${purpose}'/${coinPath}'/${accountNumber}'/0/0`,
                    outputScriptHex: outputScriptHex,
                    segwit:true,
                    additionals: ("bech32")
                });

segregated witness – How do I convert a private key in hex to a Segwit private key expected by Electrum?

I’ve been following this code to generate SegWit addresses with python. However, I’m confused because this script doesn’t output the private key in a usable way for Electrum.

I found this site which told me how to convert the key to a compressed WIF.

Here’s one example, I ran the script and got this output:

Private key: ce534f3d1f481f8736c30d866a6b2c5defe5edc36afaafc0e923586791a2462b
Verifiction key: e5ee63efe153ebf1ec537831f2fba227f4b5f80275e750a9d0a8284c9fb4f91fb5427e034ffec25bacc346263f0f6281f951926f924f7c53f771f632ca9e3cbb
Compressed public key: 03e5ee63efe153ebf1ec537831f2fba227f4b5f80275e750a9d0a8284c9fb4f91f
keyhash: 17f022e2c24238760a0a1b070eaa456df4e8b915
Native address: bc1qzlcz9ckzggu8vzs2rvrsa2j9dh6w3wg4atezy6
P2WPKH_V0: 001417f022e2c24238760a0a1b070eaa456df4e8b915
Hashed P2WPKH_VO: b9502db522524782980563a09355fa7052ee7ff1
P2SH_P2WPKH_V0: a9b9502db522524782980563a09355fa7052ee7ff187
Checksum: 7fcb7c1d
Binary address: 05b9502db522524782980563a09355fa7052ee7ff17fcb7c1d
Nested address: 3JarywCp1dbFiykdGNWyo5pdZyvSLEGZ96

I then added my own additional code to convert to WIF.

WIF: 5KP9tSHuzYd1WTCTwr5ewace9eNM8Kv8xjsWYyELHdEkKcQkiUZ
Compressed WIF: L48nE2detzZwEzdbw5dYTuNJy9wDqLVY92DwS7Br8NwgD6S8NiyT

I imported the compressed WIF key into Electrum, but I get 13BaDNdBXkfrGkvJT41HNosBBbbLZRWyZJ as a public key. Everything online confirms that only legacy addresses begin with a ‘1’, but surely it is a SegWit address, no?.

When I view ‘details’, Electrum gives me the correct compressed public key (03e5ee63efe153ebf1ec537831f2fba227f4b5f80275e750a9d0a8284c9fb4f91f).

Why doesn’t Electrum give me a bech32 address or a nested address? Have I done the correct conversion of the private key?

Here’s my code just in case there’s an obvious mistake somehow.

fullkey = '80' + (private_key.hex())
sha256a = hashlib.sha256(binascii.unhexlify(fullkey)).hexdigest()
sha256b = hashlib.sha256(binascii.unhexlify(sha256a)).hexdigest()
WIF = base58.b58encode(binascii.unhexlify(fullkey+sha256b(:8)))

compressedPubKey = private_key.hex()+'01'
compressed_fullkey = '80' + (compressedPubKey)
compressed_sha256a = hashlib.sha256(binascii.unhexlify(compressed_fullkey)).hexdigest()
compressed_sha256b = hashlib.sha256(binascii.unhexlify(compressed_sha256a)).hexdigest()
compressed_WIF = base58.b58encode(binascii.unhexlify(compressed_fullkey+compressed_sha256b(:8)))

segregated witness – Were anyone-can-spend transactions valid before SegWit?

Non-segwit nodes (legacy nodes) see segwit transactions as anyone-can-spend (ACS) transactions. It is clear that such a nodes can (and do) validate blocks containing ACS transactions, because the scripts they run are compatible with the original rules of Bitcoin (this is why SegWit is considered a soft fork). However, I see around the statement that a miner running a non-segwit node cannot include a ACS transaction in his own mining block, because, if he had managed to mine that block, segwits nodes would reject it because digital signatures were missing, resulting in an orphaned block.

Is it correct what I’m saying? If yes, let me consider the following scenario BEFORE the creation and implementation of SegWit on Bitcoin:

Before the creation and implementation of SegWit, when all running nodes were non-segwit, if a miner had included an ACS transaction in his own block and he had managed to mine it, would such a block be accepted by others nodes? I don’t see the reason why such a block could be forbidden. From the point of view of the other nodes (which are all non-segwit), they see this new block a one containing ACS transactions, and like any other block nowadays, they should validate it.

What I’m trying to say is that, in the previous version of Bitcoin (before SegWit), there was nothing to “prohibit” a miner from spending/stealing someone else’s funds. If the answer is that before SegWit nodes would never accept blocks containing ACS transactions, this means that SegWit is in fact a hard fork, because nowadays they do accept them.

Hence, I see the following three “scenarios”

  1. Before SegWit implementation, miners could include ACS transactions in their blocks and all the other nodes should validate them. The fact that it never happened is because all miners were “honest”.
  2. Before SegWit, nodes did not validate blocks containing ACS transactions. But they do validate them now. This results in a HARD fork.
  3. There is something that I’m missing or I’m misunderstanding.

I hope the answer is number 3. I’ll appreciate if somebody could help me.

segregated witness – How are segwit block transactions verified?

This is not correct.

All segwit blocks do differently is having the witnesses (which include the signature) in a separately-hashed area. They’re still an integral part of the block, and full validation cannot proceed without the witness data. Removing or altering the witness data will invalidate a block.

What this does permit is stripping the witness data without affecting validity according to pre-segwit validation rules. This is the basis for using segwit as a blocksize increase (the old 1 MB block size limit thus only applies to the non-witness part, as old nodes don’t see the witness data). However, nodes that implement the segwit rules need the full witness.

segregated witness – What is the new segwit network option on binance and how does it work?

Stack Exchange Network


Stack Exchange network consists of 176 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Visit Stack Exchange

segregated witness – Can you send a transaction from non-native segwit to native(bech32) segwit address?

All script types are compatible

This somewhat depends on the wallet client, as there is nothing in the bitcoin core code that prevents any address type from sending to any other address type. The type of address/UTXO is determined by how it was sent. Coins that were at one point transacted between SegWit addresses, but made their way to a legacy address, will create a legacy UTXO.

Common Scenario

When you receive bitcoin (UTXO), it is from one of the protocols. Your SegWit address can receive coins from a legacy address; but this does not “upgrade” the coins to benefit from SegWit improvements, they are still legacy “coins”. Mixed script transactions are a feature that enables you to spend UTXOs in a single transaction that may have come from different script types.

Transaction Example:

  • You receive 0.5 BTC to a SegWit address from a legacy address.
  • You already have 0.5 BTC that were sent using SegWit.
  • You send a 1 BTC transaction, which uses both the legacy and SegWit UTXOs, from a SegWit enabled wallet. The 0.5 BTC that was already SegWit will take advantage of the transaction fee updates, etc. The legacy UTXO will not.
  • The resulting 1 BTC in the receiving address is a SegWit UTXO, and any further movement of the coins will benefit from SegWit improvements, unless at some point they are sent back to a legacy address, where they again become “legacy coins”

So yes, you can send UTXOs of any protocol type to any other, but your wallet client must be able to recognize the address protocol in order to send to it. Even if you are using a wallet client with only legacy addresses and no SegWit support, the source code is backwards compatible, you will receive the coins, but when spending the UTXO, you cannot take advantage of the SegWit improvements.

segregated witness – Can you break down what data is encoded into a bech32 address?

bech32 addresses are defined in BIP 173. A list of address prefixes on the Bitcoin wiki is here.

This slide is taken from Pieter Wuille’s presentation on bech32 at SF Bitcoin Devs in March 2017.

bech32 structure slide

  • bc is representing Bitcoin (mainnet) and is human readable.

  • Testnet bech32 addresses start tb

  • Signet (both default Signet and custom Signets) bech32 addresses also start tb (although an earlier iteration of Signet used sb).

  • Regtest bech32 addresses start with bcrt. This is defined in chainparams.cpp here.

  • 1 is just a separator and doesn’t represent any particular data

  • q is the witness version. This represents zero as the first SegWit witness version introduced was SegWit v0. Taproot introduces SegWit v1.

  • w508d6qejxtdg4y5r3zarvary0c5xw7k is the hash of the witness program.

  • v8f3t4 is the checksum

As the slide says, mainnet P2WPKH addresses are 42 characters and mainnet P2WSH addressses are 62 characters under SegWit v0. Future witness versions can be up to 74 characters although SegWit v1 addresses (Taproot) will be the same length as v0 P2WSH addresses (62 characters). Witness programs as defined under SegWit v1 are 32 bytes.

There is a bech32 demo decoder site here.