// makeTestOutput creates an on-chain output paying to a freshly generated // p2pkh output with the specified amount. func makeTestOutput(r *rpctest.Harness, t *testing.T, amt btcutil.Amount) (*btcec.PrivateKey, *wire.OutPoint, []byte, error) { // Create a fresh key, then send some coins to an address spendable by // that key. key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, nil, err } // Using the key created above, generate a pkScript which it's able to // spend. a, err := btcutil.NewAddressPubKey(key.PubKey().SerializeCompressed(), r.ActiveNet) if err != nil { return nil, nil, nil, err } selfAddrScript, err := txscript.PayToAddrScript(a.AddressPubKeyHash()) if err != nil { return nil, nil, nil, err } output := &wire.TxOut{PkScript: selfAddrScript, Value: 1e8} // Next, create and broadcast a transaction paying to the output. fundTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) if err != nil { return nil, nil, nil, err } txHash, err := r.Node.SendRawTransaction(fundTx, true) if err != nil { return nil, nil, nil, err } // The transaction created above should be included within the next // generated block. blockHash, err := r.Node.Generate(1) if err != nil { return nil, nil, nil, err } assertTxInBlock(r, t, blockHash[0], txHash) // Locate the output index of the coins spendable by the key we // generated above, this is needed in order to create a proper utxo for // this output. var outputIndex uint32 if bytes.Equal(fundTx.TxOut[0].PkScript, selfAddrScript) { outputIndex = 0 } else { outputIndex = 1 } utxo := &wire.OutPoint{ Hash: fundTx.TxHash(), Index: outputIndex, } return key, utxo, selfAddrScript, nil }
// createCSVOutput creates an output paying to a trivially redeemable CSV // pkScript with the specified time-lock. func createCSVOutput(r *rpctest.Harness, t *testing.T, numSatoshis btcutil.Amount, timeLock int32, isSeconds bool) ([]byte, *wire.OutPoint, *wire.MsgTx, error) { // Convert the time-lock to the proper sequence lock based according to // if the lock is seconds or time based. sequenceLock := blockchain.LockTimeToSequence(isSeconds, uint32(timeLock)) // Our CSV script is simply: <sequenceLock> OP_CSV OP_DROP b := txscript.NewScriptBuilder(). AddInt64(int64(sequenceLock)). AddOp(txscript.OP_CHECKSEQUENCEVERIFY). AddOp(txscript.OP_DROP) csvScript, err := b.Script() if err != nil { return nil, nil, nil, err } // Using the script generated above, create a P2SH output which will be // accepted into the mempool. p2shAddr, err := btcutil.NewAddressScriptHash(csvScript, r.ActiveNet) if err != nil { return nil, nil, nil, err } p2shScript, err := txscript.PayToAddrScript(p2shAddr) if err != nil { return nil, nil, nil, err } output := &wire.TxOut{ PkScript: p2shScript, Value: int64(numSatoshis), } // Finally create a valid transaction which creates the output crafted // above. tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) if err != nil { return nil, nil, nil, err } var outputIndex uint32 if !bytes.Equal(tx.TxOut[0].PkScript, p2shScript) { outputIndex = 1 } utxo := &wire.OutPoint{ Hash: tx.TxHash(), Index: outputIndex, } return csvScript, utxo, tx, nil }