2021-08-23 10:35:48 +02:00
|
|
|
//go:build dev
|
2018-09-20 12:21:32 +02:00
|
|
|
// +build dev
|
2018-08-17 04:29:37 +02:00
|
|
|
|
|
|
|
package chainntnfs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
2018-08-17 04:29:37 +02:00
|
|
|
"github.com/btcsuite/btcd/btcjson"
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
2018-08-17 04:29:37 +02:00
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcd/integration/rpctest"
|
|
|
|
"github.com/btcsuite/btcd/txscript"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
2024-07-19 08:05:28 +02:00
|
|
|
"github.com/lightningnetwork/lnd/input"
|
2024-03-15 12:54:36 +01:00
|
|
|
"github.com/lightningnetwork/lnd/lntest/unittest"
|
2022-05-05 22:11:50 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-08-17 04:29:37 +02:00
|
|
|
)
|
|
|
|
|
2018-08-24 13:50:47 +02:00
|
|
|
var (
|
2018-10-21 01:27:46 +02:00
|
|
|
// TrickleInterval is the interval at which the miner should trickle
|
2018-08-24 13:50:47 +02:00
|
|
|
// transactions to its peers. We'll set it small to ensure the miner
|
|
|
|
// propagates transactions quickly in the tests.
|
2018-10-21 01:27:46 +02:00
|
|
|
TrickleInterval = 10 * time.Millisecond
|
2018-08-24 13:50:47 +02:00
|
|
|
)
|
|
|
|
|
2018-12-07 06:14:34 +01:00
|
|
|
// randPubKeyHashScript generates a P2PKH script that pays to the public key of
|
|
|
|
// a randomly-generated private key.
|
|
|
|
func randPubKeyHashScript() ([]byte, *btcec.PrivateKey, error) {
|
2022-02-23 14:48:00 +01:00
|
|
|
privKey, err := btcec.NewPrivateKey()
|
2018-12-07 06:14:34 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
2018-08-17 04:29:37 +02:00
|
|
|
}
|
2018-12-07 06:14:34 +01:00
|
|
|
|
|
|
|
pubKeyHash := btcutil.Hash160(privKey.PubKey().SerializeCompressed())
|
2024-07-19 08:05:28 +02:00
|
|
|
addrScript, err := btcutil.NewAddressWitnessPubKeyHash(
|
2024-03-15 12:54:36 +01:00
|
|
|
pubKeyHash, unittest.NetParams,
|
|
|
|
)
|
2018-12-07 06:14:34 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
pkScript, err := txscript.PayToAddrScript(addrScript)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return pkScript, privKey, nil
|
|
|
|
}
|
2018-08-17 04:29:37 +02:00
|
|
|
|
|
|
|
// GetTestTxidAndScript generate a new test transaction and returns its txid and
|
|
|
|
// the script of the output being generated.
|
|
|
|
func GetTestTxidAndScript(h *rpctest.Harness) (*chainhash.Hash, []byte, error) {
|
2018-12-07 06:14:34 +01:00
|
|
|
pkScript, _, err := randPubKeyHashScript()
|
2018-08-17 04:29:37 +02:00
|
|
|
if err != nil {
|
2024-02-26 12:19:38 +01:00
|
|
|
return nil, nil, fmt.Errorf("unable to generate pkScript: %w",
|
|
|
|
err)
|
2018-08-17 04:29:37 +02:00
|
|
|
}
|
2018-12-07 06:14:34 +01:00
|
|
|
output := &wire.TxOut{Value: 2e8, PkScript: pkScript}
|
2018-08-17 04:29:37 +02:00
|
|
|
txid, err := h.SendOutputs([]*wire.TxOut{output}, 10)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2018-12-07 06:14:34 +01:00
|
|
|
return txid, pkScript, nil
|
2018-08-17 04:29:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// WaitForMempoolTx waits for the txid to be seen in the miner's mempool.
|
|
|
|
func WaitForMempoolTx(miner *rpctest.Harness, txid *chainhash.Hash) error {
|
|
|
|
timeout := time.After(10 * time.Second)
|
2018-10-21 01:27:46 +02:00
|
|
|
trickle := time.After(2 * TrickleInterval)
|
2018-08-17 04:29:37 +02:00
|
|
|
for {
|
|
|
|
// Check for the harness' knowledge of the txid.
|
2021-03-09 23:12:26 +01:00
|
|
|
tx, err := miner.Client.GetRawTransaction(txid)
|
2018-08-17 04:29:37 +02:00
|
|
|
if err != nil {
|
|
|
|
jsonErr, ok := err.(*btcjson.RPCError)
|
|
|
|
if ok && jsonErr.Code == btcjson.ErrRPCNoTxInfo {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if tx != nil && tx.Hash().IsEqual(txid) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(100 * time.Millisecond):
|
|
|
|
case <-timeout:
|
|
|
|
return errors.New("timed out waiting for tx")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-24 13:50:47 +02:00
|
|
|
// To ensure any transactions propagate from the miner to the peers
|
|
|
|
// before returning, ensure we have waited for at least
|
|
|
|
// 2*trickleInterval before returning.
|
|
|
|
select {
|
|
|
|
case <-trickle:
|
|
|
|
case <-timeout:
|
|
|
|
return errors.New("timeout waiting for trickle interval. " +
|
|
|
|
"Trickle interval to large?")
|
|
|
|
}
|
|
|
|
|
2018-08-17 04:29:37 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateSpendableOutput creates and returns an output that can be spent later
|
|
|
|
// on.
|
2018-12-07 06:14:34 +01:00
|
|
|
func CreateSpendableOutput(t *testing.T,
|
|
|
|
miner *rpctest.Harness) (*wire.OutPoint, *wire.TxOut, *btcec.PrivateKey) {
|
|
|
|
|
2018-08-17 04:29:37 +02:00
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
// Create a transaction that only has one output, the one destined for
|
|
|
|
// the recipient.
|
2018-12-07 06:14:34 +01:00
|
|
|
pkScript, privKey, err := randPubKeyHashScript()
|
2022-05-05 22:11:50 +02:00
|
|
|
require.NoError(t, err, "unable to generate pkScript")
|
2018-12-07 06:14:34 +01:00
|
|
|
output := &wire.TxOut{Value: 2e8, PkScript: pkScript}
|
2018-08-17 04:29:37 +02:00
|
|
|
txid, err := miner.SendOutputsWithoutChange([]*wire.TxOut{output}, 10)
|
2022-05-05 22:11:50 +02:00
|
|
|
require.NoError(t, err, "unable to create tx")
|
2018-08-17 04:29:37 +02:00
|
|
|
|
|
|
|
// Mine the transaction to mark the output as spendable.
|
|
|
|
if err := WaitForMempoolTx(miner, txid); err != nil {
|
|
|
|
t.Fatalf("tx not relayed to miner: %v", err)
|
|
|
|
}
|
2021-03-09 23:12:26 +01:00
|
|
|
if _, err := miner.Client.Generate(1); err != nil {
|
2018-08-17 04:29:37 +02:00
|
|
|
t.Fatalf("unable to generate single block: %v", err)
|
|
|
|
}
|
|
|
|
|
2018-12-07 06:14:34 +01:00
|
|
|
return wire.NewOutPoint(txid, 0), output, privKey
|
2018-08-17 04:29:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreateSpendTx creates a transaction spending the specified output.
|
2018-12-07 06:14:34 +01:00
|
|
|
func CreateSpendTx(t *testing.T, prevOutPoint *wire.OutPoint,
|
|
|
|
prevOutput *wire.TxOut, privKey *btcec.PrivateKey) *wire.MsgTx {
|
|
|
|
|
2018-08-17 04:29:37 +02:00
|
|
|
t.Helper()
|
|
|
|
|
2024-07-19 08:05:28 +02:00
|
|
|
// Create a new output.
|
|
|
|
outputAmt := int64(1e8)
|
|
|
|
witnessProgram, _, err := randPubKeyHashScript()
|
|
|
|
require.NoError(t, err, "unable to generate pkScript")
|
|
|
|
output := wire.NewTxOut(outputAmt, witnessProgram)
|
|
|
|
|
|
|
|
// Create a new tx.
|
|
|
|
tx := wire.NewMsgTx(2)
|
|
|
|
tx.AddTxIn(wire.NewTxIn(prevOutPoint, nil, nil))
|
|
|
|
tx.AddTxOut(output)
|
|
|
|
|
|
|
|
// Generate the witness.
|
|
|
|
sigHashes := input.NewTxSigHashesV0Only(tx)
|
|
|
|
witnessScript, err := txscript.WitnessSignature(
|
|
|
|
tx, sigHashes, 0, prevOutput.Value, prevOutput.PkScript,
|
|
|
|
txscript.SigHashAll, privKey, true,
|
2018-08-17 04:29:37 +02:00
|
|
|
)
|
2022-05-05 22:11:50 +02:00
|
|
|
require.NoError(t, err, "unable to sign tx")
|
2018-08-17 04:29:37 +02:00
|
|
|
|
2024-07-19 08:05:28 +02:00
|
|
|
tx.TxIn[0].Witness = witnessScript
|
|
|
|
|
|
|
|
return tx
|
2018-08-17 04:29:37 +02:00
|
|
|
}
|