user128539: i experimented a lot with p2wsh multisig configurations with bitcoinjs-lib. but when i tried to sign a standard native segwit p2wpkh to p2wpkh transaction everything goes ok except for bitcoin-cli sendrawtransaction. it says
non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)

js code (./btc is here, the rest can be npm installed):
const { btc, send, listunspent, getnewaddress, bech32toScriptPubKey } = require('./btc')();
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.testnet;
const hashtype = bitcoin.Transaction.SIGHASH_ALL;
const ECPair = require('ecpair').ECPairFactory(require('tiny-secp256k1'));
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('close', () => process.exit(0));

const input = q => new Promise(r => rl.question(q, r));

main();

async function main() {
    const u = (await listunspent(0, 0, true)).filter(x => x.solvable && x.spendable && x.desc.startsWith('wpkh'));

    console.log(u);

    const v = await input('Which input to use? ');

    const utxo = u[parseInt(v)];

    if (!utxo) {
        console.log('error');
        process.exit(1);
    }

    var out = await input('Output address (leave empty to generate a new one) ');

    if (out.length == 0) {
        out = await getnewaddress();
    }

    if (out.length != 42) {
        console.log('p2wpkh addresses are 42 chars long');
        process.exit(1);
    }

    const ecpair = ECPair.fromWIF(await btc('dumpprivkey', utxo.address), network);

    const tx = new bitcoin.Transaction(network);

    tx.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.vout);

    const fee = 110;

    tx.addOutput(bech32toScriptPubKey(out), utxo.amount - fee);

    const sighash = tx.hashForWitnessV0(
        0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype
    );

    tx.setWitness(0, [
        bitcoin.script.signature.encode(ecpair.sign(sighash), hashtype),
        ecpair.publicKey
    ]);

    console.log(tx.toHex());
    console.log(await send(tx.toHex()));
}

TX hex
01000000000101c690a8157bb45506b15173a3175bd3504182cf8c91f916235522522a3d1a28280100000000ffffffff01d2410f00000000001600149b959b78f09b7f7976391fd20aad3835b738e0c3024730440220120a950d96210c48a6831e7ee7f746e6119183d8512b10a6b14c60509556bba3022042359f1699e9cfb90637647ecb085e262736dc5ad9c076666cb44c29c20baafc0121027b612527ff9e157b80dd2ddac0e11555afcd517a7a425c27e5c7afbad889528e00000000

i think i am making a mistake in what must be included in the sighash. What scriptPubKey is used in the sighash of a p2wpkh?

user128539: i have fixed the problem by using a P2PKH output script for the sighash
const sighash = tx.hashForWitnessV0(
    0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype
);

has been changed to
const pkh = bitcoin.script.decompile(Buffer.from(utxo.scriptPubKey, 'hex'))[1];

const sighash = tx.hashForWitnessV0(
    0, bitcoin.script.compile([
        bitcoin.opcodes.OP_DUP,
        bitcoin.opcodes.OP_HASH160,
        pkh,
        bitcoin.opcodes.OP_EQUALVERIFY,
        bitcoin.opcodes.OP_CHECKSIG
    ]), utxo.amount, hashtype
);

my script now works and added it to my Bitcoin stuff repo

https://github.com/antonilol/btc_stuff

https://github.com/antonilol/btc_stuff/blob/master/p2wpkh.js

128539: <p>i experimented a lot with p2wsh multisig configurations with <code>bitcoinjs-lib</code>. but when i tried to sign a standard native segwit p2wpkh to p2wpkh transaction everything goes ok except for <code>bitcoin-cli sendrawtransaction</code>. it says</p>
<pre><code>non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation)
</code></pre>
<p>js code (<code>./btc</code> is <a href="https://github.com/antonilol/btc_stuff" rel="nofollow noreferrer">here</a>, the rest can be <code>npm install</code>ed):</p>
<pre><code>const { btc, send, listunspent, getnewaddress, bech32toScriptPubKey } = require('./btc')();
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.testnet;
const hashtype = bitcoin.Transaction.SIGHASH_ALL;
const ECPair = require('ecpair').ECPairFactory(require('tiny-secp256k1'));
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('close', () =&gt; process.exit(0));

const input = q =&gt; new Promise(r =&gt; rl.question(q, r));

main();

async function main() {
    const u = (await listunspent(0, 0, true)).filter(x =&gt; x.solvable &amp;&amp; x.spendable &amp;&amp; x.desc.startsWith('wpkh'));

    console.log(u);

    const v = await input('Which input to use? ');

    const utxo = u[parseInt(v)];

    if (!utxo) {
        console.log('error');
        process.exit(1);
    }

    var out = await input('Output address (leave empty to generate a new one) ');

    if (out.length == 0) {
        out = await getnewaddress();
    }

    if (out.length != 42) {
        console.log('p2wpkh addresses are 42 chars long');
        process.exit(1);
    }

    const ecpair = ECPair.fromWIF(await btc('dumpprivkey', utxo.address), network);

    const tx = new bitcoin.Transaction(network);

    tx.addInput(Buffer.from(utxo.txid, 'hex').reverse(), utxo.vout);

    const fee = 110;

    tx.addOutput(bech32toScriptPubKey(out), utxo.amount - fee);

    const sighash = tx.hashForWitnessV0(
        0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype
    );

    tx.setWitness(0, [
        bitcoin.script.signature.encode(ecpair.sign(sighash), hashtype),
        ecpair.publicKey
    ]);

    console.log(tx.toHex());
    console.log(await send(tx.toHex()));
}
</code></pre>
<p>TX hex</p>
<pre><code>01000000000101c690a8157bb45506b15173a3175bd3504182cf8c91f916235522522a3d1a28280100000000ffffffff01d2410f00000000001600149b959b78f09b7f7976391fd20aad3835b738e0c3024730440220120a950d96210c48a6831e7ee7f746e6119183d8512b10a6b14c60509556bba3022042359f1699e9cfb90637647ecb085e262736dc5ad9c076666cb44c29c20baafc0121027b612527ff9e157b80dd2ddac0e11555afcd517a7a425c27e5c7afbad889528e00000000
</code></pre>
<p>i think i am making a mistake in what must be included in the sighash. What <code>scriptPubKey</code> is used in the sighash of a p2wpkh?</p>
 128539: <p>i have fixed the problem by using a P2PKH output script for the sighash</p>
<pre><code>const sighash = tx.hashForWitnessV0(
    0, Buffer.from(utxo.scriptPubKey, 'hex'), utxo.amount, hashtype
);
</code></pre>
<p>has been changed to</p>
<pre><code>const pkh = bitcoin.script.decompile(Buffer.from(utxo.scriptPubKey, 'hex'))[1];

const sighash = tx.hashForWitnessV0(
    0, bitcoin.script.compile([
        bitcoin.opcodes.OP_DUP,
        bitcoin.opcodes.OP_HASH160,
        pkh,
        bitcoin.opcodes.OP_EQUALVERIFY,
        bitcoin.opcodes.OP_CHECKSIG
    ]), utxo.amount, hashtype
);
</code></pre>
<p>my script now works and added it to my Bitcoin stuff repo
<br>
<a href="https://github.com/antonilol/btc_stuff" rel="nofollow noreferrer">https://github.com/antonilol/btc_stuff</a>
<br>
<a href="https://github.com/antonilol/btc_stuff/blob/master/p2wpkh.js" rel="nofollow noreferrer">https://github.com/antonilol/btc_stuff/blob/master/p2wpkh.js</a></p>
