MetacoSA / NBitcoin

Comprehensive Bitcoin library for the .NET framework.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Failing to P2WPKH

ferib opened this issue · comments

I have been reading over the docs but failed to create a P2WPKH transaction that is accepted with my Ledger X Device.

I am trying to use the below NBitcoin snippet (for Litecoin, but I assume this to be similar to Bitcoin)

var selectedNetwork = Litecoin.Instance.Mainnet;
            TransactionBuilder txBuilder = selectedNetwork.CreateTransactionBuilder();
            var fundingRaw = Transaction.Parse(
                "01000000011142ee910c500c9013cb0028d98ab0d8beebbd75b63c9bca825b700fc8ce36ad000000006b483045022100b6fd9e5d84ff5be5c42cd14e6596e9c8a139d9b75c6e4442de8f7e72a38c6def02201b4651d9d23b17a693fd2486f6bb5890f7143cced0c2e0be12d4579df49fd109012103f5bb4422fb850366daffb567dd1d4bcebb8cd95b85c5bd087bcbecdb9407e694ffffffff0200e1f50500000000160014f9d7821150c622e735113a240681c1ee7233c8f408af3f71000000001976a9147ced4bcfe2797db1c141277cdf5c2a4a7f5ede5188ac00000000",
                selectedNetwork);
            
            txBuilder.AddCoins(new Coin(fundingRaw, 0));

            // dummy segwith receiver for P2WPKH
            var key = new Key();
            var secret = key.GetBitcoinSecret(SelectedNetwork);
            var addr = secret.GetSegwitAddress();
            txBuilder.SendAll(addr);
            var tx = txBuilder.BuildTransaction(false);

            string debug = tx.ToHex();

The docs tells me a P2WPKH should be similar to P2PKH, yet I somehow fail to correctly add my witness data?

In NBitcoin, spending a P2WPKH output is no different from spending a normal P2PKH.

My intention is to take the raw tx hex string (debug) and push this into my Ledger X using another project, however, the Ledger device does not 'trust' the input. My assumption is that I screwed up the transaction from the start as witness data is missing?

(I do not own the private keys directly and therefore am unable to add them to the TransactionBuilder)

What do you use to "push this into your ledger X"?

The trust input error in ledger X only means that your transaction should include the previous transactions in the PSBT.
Normally you can ignore the error though.

Use the txBuilder to build the PSBT, then use psbt.AddTransaction to add the fundingRaw to the PSBT. Then push the PSBT to ledger.

Though I am not too sure about what you mean by "pushing to ledger X". If you want to sign with your ledger X, then you need additional information in the PSBT such as the derivation key path.

What do you use to "push this into your ledger X"?

I used this repo, https://github.com/LedgerHQ/ledger-dotnet-api

The trust input error in ledger X only means that your transaction should include the previous transactions in the PSBT.
Normally you can ignore the error though.

I called the ledger API and included the previous transaction (fundingRaw), I got the notification of untrusted, but indeed I was able to proceed and sign the transaction. I assume I did that wrong, too as the unsigned and signed transactions weren't any different.

I will have a look at the proposed PSBT with added fundingRaw later this day, tnx

I tried adding the psbt.AddTransactions(fundingRaw) as showen below, however, when I call psbt.Finalize() right after I get this exception with message "NBitcoin.PSBTException: 'Input 0: The finalized input script does not properly validate "WitnessProgramMissmatch"'"

            var selectedNetwork = Litecoin.Instance.Mainnet;
            

            TransactionBuilder txBuilder = selectedNetwork.CreateTransactionBuilder();
            var fundingRaw = Transaction.Parse(
                "01000000011142ee910c500c9013cb0028d98ab0d8beebbd75b63c9bca825b700fc8ce36ad000000006b483045022100b6fd9e5d84ff5be5c42cd14e6596e9c8a139d9b75c6e4442de8f7e72a38c6def02201b4651d9d23b17a693fd2486f6bb5890f7143cced0c2e0be12d4579df49fd109012103f5bb4422fb850366daffb567dd1d4bcebb8cd95b85c5bd087bcbecdb9407e694ffffffff0200e1f50500000000160014f9d7821150c622e735113a240681c1ee7233c8f408af3f71000000001976a9147ced4bcfe2797db1c141277cdf5c2a4a7f5ede5188ac00000000",
                selectedNetwork);
            
            txBuilder.AddCoins(new Coin(fundingRaw, 0));

            // dummy segwith receiver for P2WPKH
            var key = new Key();
            var secret = key.GetBitcoinSecret(SelectedNetwork);
            var addr = secret.GetSegwitAddress();
            txBuilder.SendAll(addr);
            var tx = txBuilder.BuildTransaction(false);
            
            var psbt = txBuilder.BuildPSBT(false);
            psbt.AddTransactions(fundingRaw);
            psbt.Finalize(); // NBitcoin.PSBTException: 'Input 0: The finalized input script does not properly validate "WitnessProgramMissmatch"'

I am pretty sure I did something wrong regarding the witnesses that are needed for the transaction, but I fail to figure this one out myself.

Regarding the Ledger X signing, I assumed this will be the way to sign the transaction after completing it:

            var testSignedTx = await LedgerClient.SignTransactionAsync(
                new KeyPath($"m/84'/2'/0'/0/1"),
                new Coin[] { coinToSpend },
                new Transaction[] { fundingRaw },
                psbt.ExtractTransaction()
            );

Actually... the only problem I am facing is indeed the warning on my Ledger X device. I was able to sign it just fine 😅

EDIT: The second problem I seem to have is that Ledger X does not want to sign a transaction with more than 3 outputs. All else is fine 🙃