package itest import ( "testing" "github.com/btcsuite/btcd/btcutil" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/stretchr/testify/require" ) func testNonstdSweep(ht *lntest.HarnessTest) { p2shAddr, err := btcutil.NewAddressScriptHash( make([]byte, 1), harnessNetParams, ) require.NoError(ht, err) p2pkhAddr, err := btcutil.NewAddressPubKeyHash( make([]byte, 20), harnessNetParams, ) require.NoError(ht, err) p2wshAddr, err := btcutil.NewAddressWitnessScriptHash( make([]byte, 32), harnessNetParams, ) require.NoError(ht, err) p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash( make([]byte, 20), harnessNetParams, ) require.NoError(ht, err) p2trAddr, err := btcutil.NewAddressTaproot( make([]byte, 32), harnessNetParams, ) require.NoError(ht, err) tests := []struct { name string address string }{ { name: "p2sh SendCoins standardness", address: p2shAddr.EncodeAddress(), }, { name: "p2pkh SendCoins standardness", address: p2pkhAddr.EncodeAddress(), }, { name: "p2wsh SendCoins standardness", address: p2wshAddr.EncodeAddress(), }, { name: "p2wkh SendCoins standardness", address: p2wkhAddr.EncodeAddress(), }, { name: "p2tr SendCoins standardness", address: p2trAddr.EncodeAddress(), }, } for _, test := range tests { test := test success := ht.Run(test.name, func(t *testing.T) { st := ht.Subtest(t) testNonStdSweepInner(st, test.address) }) if !success { break } } } func testNonStdSweepInner(ht *lntest.HarnessTest, address string) { carol := ht.NewNode("carol", nil) // Give Carol a UTXO so SendCoins will behave as expected. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol) // Set the fee estimate to 1sat/vbyte. ht.SetFeeEstimate(250) // Make Carol call SendCoins with the SendAll flag and the created // address. sendReq := &lnrpc.SendCoinsRequest{ Addr: address, SatPerVbyte: 1, SendAll: true, } // If a non-standard transaction was created, then this SendCoins call // will fail. carol.RPC.SendCoins(sendReq) // Fetch the txid so we can grab the raw transaction. txid := ht.Miner.AssertNumTxsInMempool(1)[0] tx := ht.Miner.GetRawTransaction(txid) msgTx := tx.MsgTx() // Fetch the fee of the transaction. var ( inputVal int outputVal int fee int ) for _, inp := range msgTx.TxIn { // Fetch the previous outpoint's value. prevOut := inp.PreviousOutPoint ptx := ht.Miner.GetRawTransaction(&prevOut.Hash) pout := ptx.MsgTx().TxOut[prevOut.Index] inputVal += int(pout.Value) } for _, outp := range msgTx.TxOut { outputVal += int(outp.Value) } fee = inputVal - outputVal // Fetch the vsize of the transaction so we can determine if the // transaction pays >= 1 sat/vbyte. rawTx := ht.Miner.GetRawTransactionVerbose(txid) // Require fee >= vbytes. require.True(ht, fee >= int(rawTx.Vsize)) // Mine a block to keep the mempool clean. ht.MineBlocksAndAssertNumTxes(1, 1) }