1// Copyright (c) 2016 The btcsuite developers
2// Use of this source code is governed by an ISC
3// license that can be found in the LICENSE file.
4
5// This file is ignored during the regular tests due to the following build tag.
6// +build rpctest
7
8package integration
9
10import (
11	"bytes"
12	"runtime"
13	"strings"
14	"testing"
15	"time"
16
17	"github.com/btcsuite/btcd/blockchain"
18	"github.com/btcsuite/btcd/btcec"
19	"github.com/btcsuite/btcd/chaincfg"
20	"github.com/btcsuite/btcd/chaincfg/chainhash"
21	"github.com/btcsuite/btcd/integration/rpctest"
22	"github.com/btcsuite/btcd/txscript"
23	"github.com/btcsuite/btcd/wire"
24	"github.com/btcsuite/btcutil"
25)
26
27const (
28	csvKey = "csv"
29)
30
31// makeTestOutput creates an on-chain output paying to a freshly generated
32// p2pkh output with the specified amount.
33func makeTestOutput(r *rpctest.Harness, t *testing.T,
34	amt btcutil.Amount) (*btcec.PrivateKey, *wire.OutPoint, []byte, error) {
35
36	// Create a fresh key, then send some coins to an address spendable by
37	// that key.
38	key, err := btcec.NewPrivateKey(btcec.S256())
39	if err != nil {
40		return nil, nil, nil, err
41	}
42
43	// Using the key created above, generate a pkScript which it's able to
44	// spend.
45	a, err := btcutil.NewAddressPubKey(key.PubKey().SerializeCompressed(), r.ActiveNet)
46	if err != nil {
47		return nil, nil, nil, err
48	}
49	selfAddrScript, err := txscript.PayToAddrScript(a.AddressPubKeyHash())
50	if err != nil {
51		return nil, nil, nil, err
52	}
53	output := &wire.TxOut{PkScript: selfAddrScript, Value: 1e8}
54
55	// Next, create and broadcast a transaction paying to the output.
56	fundTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true)
57	if err != nil {
58		return nil, nil, nil, err
59	}
60	txHash, err := r.Node.SendRawTransaction(fundTx, true)
61	if err != nil {
62		return nil, nil, nil, err
63	}
64
65	// The transaction created above should be included within the next
66	// generated block.
67	blockHash, err := r.Node.Generate(1)
68	if err != nil {
69		return nil, nil, nil, err
70	}
71	assertTxInBlock(r, t, blockHash[0], txHash)
72
73	// Locate the output index of the coins spendable by the key we
74	// generated above, this is needed in order to create a proper utxo for
75	// this output.
76	var outputIndex uint32
77	if bytes.Equal(fundTx.TxOut[0].PkScript, selfAddrScript) {
78		outputIndex = 0
79	} else {
80		outputIndex = 1
81	}
82
83	utxo := &wire.OutPoint{
84		Hash:  fundTx.TxHash(),
85		Index: outputIndex,
86	}
87
88	return key, utxo, selfAddrScript, nil
89}
90
91// TestBIP0113Activation tests for proper adherence of the BIP 113 rule
92// constraint which requires all transaction finality tests to use the MTP of
93// the last 11 blocks, rather than the timestamp of the block which includes
94// them.
95//
96// Overview:
97//  - Pre soft-fork:
98//    - Transactions with non-final lock-times from the PoV of MTP should be
99//      rejected from the mempool.
100//    - Transactions within non-final MTP based lock-times should be accepted
101//      in valid blocks.
102//
103//  - Post soft-fork:
104//    - Transactions with non-final lock-times from the PoV of MTP should be
105//      rejected from the mempool and when found within otherwise valid blocks.
106//    - Transactions with final lock-times from the PoV of MTP should be
107//      accepted to the mempool and mined in future block.
108func TestBIP0113Activation(t *testing.T) {
109	t.Parallel()
110
111	btcdCfg := []string{"--rejectnonstd"}
112	r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg)
113	if err != nil {
114		t.Fatal("unable to create primary harness: ", err)
115	}
116	if err := r.SetUp(true, 1); err != nil {
117		t.Fatalf("unable to setup test chain: %v", err)
118	}
119	defer r.TearDown()
120
121	// Create a fresh output for usage within the test below.
122	const outputValue = btcutil.SatoshiPerBitcoin
123	outputKey, testOutput, testPkScript, err := makeTestOutput(r, t,
124		outputValue)
125	if err != nil {
126		t.Fatalf("unable to create test output: %v", err)
127	}
128
129	// Fetch a fresh address from the harness, we'll use this address to
130	// send funds back into the Harness.
131	addr, err := r.NewAddress()
132	if err != nil {
133		t.Fatalf("unable to generate address: %v", err)
134	}
135	addrScript, err := txscript.PayToAddrScript(addr)
136	if err != nil {
137		t.Fatalf("unable to generate addr script: %v", err)
138	}
139
140	// Now create a transaction with a lock time which is "final" according
141	// to the latest block, but not according to the current median time
142	// past.
143	tx := wire.NewMsgTx(1)
144	tx.AddTxIn(&wire.TxIn{
145		PreviousOutPoint: *testOutput,
146	})
147	tx.AddTxOut(&wire.TxOut{
148		PkScript: addrScript,
149		Value:    outputValue - 1000,
150	})
151
152	// We set the lock-time of the transaction to just one minute after the
153	// current MTP of the chain.
154	chainInfo, err := r.Node.GetBlockChainInfo()
155	if err != nil {
156		t.Fatalf("unable to query for chain info: %v", err)
157	}
158	tx.LockTime = uint32(chainInfo.MedianTime) + 1
159
160	sigScript, err := txscript.SignatureScript(tx, 0, testPkScript,
161		txscript.SigHashAll, outputKey, true)
162	if err != nil {
163		t.Fatalf("unable to generate sig: %v", err)
164	}
165	tx.TxIn[0].SignatureScript = sigScript
166
167	// This transaction should be rejected from the mempool as using MTP
168	// for transactions finality is now a policy rule. Additionally, the
169	// exact error should be the rejection of a non-final transaction.
170	_, err = r.Node.SendRawTransaction(tx, true)
171	if err == nil {
172		t.Fatalf("transaction accepted, but should be non-final")
173	} else if !strings.Contains(err.Error(), "not finalized") {
174		t.Fatalf("transaction should be rejected due to being "+
175			"non-final, instead: %v", err)
176	}
177
178	// However, since the block validation consensus rules haven't yet
179	// activated, a block including the transaction should be accepted.
180	txns := []*btcutil.Tx{btcutil.NewTx(tx)}
181	block, err := r.GenerateAndSubmitBlock(txns, -1, time.Time{})
182	if err != nil {
183		t.Fatalf("unable to submit block: %v", err)
184	}
185	txid := tx.TxHash()
186	assertTxInBlock(r, t, block.Hash(), &txid)
187
188	// At this point, the block height should be 103: we mined 101 blocks
189	// to create a single mature output, then an additional block to create
190	// a new output, and then mined a single block above to include our
191	// transaction.
192	assertChainHeight(r, t, 103)
193
194	// Next, mine enough blocks to ensure that the soft-fork becomes
195	// activated. Assert that the block version of the second-to-last block
196	// in the final range is active.
197
198	// Next, mine ensure blocks to ensure that the soft-fork becomes
199	// active. We're at height 103 and we need 200 blocks to be mined after
200	// the genesis target period, so we mine 196 blocks. This'll put us at
201	// height 299. The getblockchaininfo call checks the state for the
202	// block AFTER the current height.
203	numBlocks := (r.ActiveNet.MinerConfirmationWindow * 2) - 4
204	if _, err := r.Node.Generate(numBlocks); err != nil {
205		t.Fatalf("unable to generate blocks: %v", err)
206	}
207
208	assertChainHeight(r, t, 299)
209	assertSoftForkStatus(r, t, csvKey, blockchain.ThresholdActive)
210
211	// The timeLockDeltas slice represents a series of deviations from the
212	// current MTP which will be used to test border conditions w.r.t
213	// transaction finality. -1 indicates 1 second prior to the MTP, 0
214	// indicates the current MTP, and 1 indicates 1 second after the
215	// current MTP.
216	//
217	// This time, all transactions which are final according to the MTP
218	// *should* be accepted to both the mempool and within a valid block.
219	// While transactions with lock-times *after* the current MTP should be
220	// rejected.
221	timeLockDeltas := []int64{-1, 0, 1}
222	for _, timeLockDelta := range timeLockDeltas {
223		chainInfo, err = r.Node.GetBlockChainInfo()
224		if err != nil {
225			t.Fatalf("unable to query for chain info: %v", err)
226		}
227		medianTimePast := chainInfo.MedianTime
228
229		// Create another test output to be spent shortly below.
230		outputKey, testOutput, testPkScript, err = makeTestOutput(r, t,
231			outputValue)
232		if err != nil {
233			t.Fatalf("unable to create test output: %v", err)
234		}
235
236		// Create a new transaction with a lock-time past the current known
237		// MTP.
238		tx = wire.NewMsgTx(1)
239		tx.AddTxIn(&wire.TxIn{
240			PreviousOutPoint: *testOutput,
241		})
242		tx.AddTxOut(&wire.TxOut{
243			PkScript: addrScript,
244			Value:    outputValue - 1000,
245		})
246		tx.LockTime = uint32(medianTimePast + timeLockDelta)
247		sigScript, err = txscript.SignatureScript(tx, 0, testPkScript,
248			txscript.SigHashAll, outputKey, true)
249		if err != nil {
250			t.Fatalf("unable to generate sig: %v", err)
251		}
252		tx.TxIn[0].SignatureScript = sigScript
253
254		// If the time-lock delta is greater than -1, then the
255		// transaction should be rejected from the mempool and when
256		// included within a block. A time-lock delta of -1 should be
257		// accepted as it has a lock-time of one
258		// second _before_ the current MTP.
259
260		_, err = r.Node.SendRawTransaction(tx, true)
261		if err == nil && timeLockDelta >= 0 {
262			t.Fatal("transaction was accepted into the mempool " +
263				"but should be rejected!")
264		} else if err != nil && !strings.Contains(err.Error(), "not finalized") {
265			t.Fatalf("transaction should be rejected from mempool "+
266				"due to being  non-final, instead: %v", err)
267		}
268
269		txns = []*btcutil.Tx{btcutil.NewTx(tx)}
270		_, err := r.GenerateAndSubmitBlock(txns, -1, time.Time{})
271		if err == nil && timeLockDelta >= 0 {
272			t.Fatal("block should be rejected due to non-final " +
273				"txn, but was accepted")
274		} else if err != nil && !strings.Contains(err.Error(), "unfinalized") {
275			t.Fatalf("block should be rejected due to non-final "+
276				"tx, instead: %v", err)
277		}
278	}
279}
280
281// createCSVOutput creates an output paying to a trivially redeemable CSV
282// pkScript with the specified time-lock.
283func createCSVOutput(r *rpctest.Harness, t *testing.T,
284	numSatoshis btcutil.Amount, timeLock int32,
285	isSeconds bool) ([]byte, *wire.OutPoint, *wire.MsgTx, error) {
286
287	// Convert the time-lock to the proper sequence lock based according to
288	// if the lock is seconds or time based.
289	sequenceLock := blockchain.LockTimeToSequence(isSeconds,
290		uint32(timeLock))
291
292	// Our CSV script is simply: <sequenceLock> OP_CSV OP_DROP
293	b := txscript.NewScriptBuilder().
294		AddInt64(int64(sequenceLock)).
295		AddOp(txscript.OP_CHECKSEQUENCEVERIFY).
296		AddOp(txscript.OP_DROP)
297	csvScript, err := b.Script()
298	if err != nil {
299		return nil, nil, nil, err
300	}
301
302	// Using the script generated above, create a P2SH output which will be
303	// accepted into the mempool.
304	p2shAddr, err := btcutil.NewAddressScriptHash(csvScript, r.ActiveNet)
305	if err != nil {
306		return nil, nil, nil, err
307	}
308	p2shScript, err := txscript.PayToAddrScript(p2shAddr)
309	if err != nil {
310		return nil, nil, nil, err
311	}
312	output := &wire.TxOut{
313		PkScript: p2shScript,
314		Value:    int64(numSatoshis),
315	}
316
317	// Finally create a valid transaction which creates the output crafted
318	// above.
319	tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true)
320	if err != nil {
321		return nil, nil, nil, err
322	}
323
324	var outputIndex uint32
325	if !bytes.Equal(tx.TxOut[0].PkScript, p2shScript) {
326		outputIndex = 1
327	}
328
329	utxo := &wire.OutPoint{
330		Hash:  tx.TxHash(),
331		Index: outputIndex,
332	}
333
334	return csvScript, utxo, tx, nil
335}
336
337// spendCSVOutput spends an output previously created by the createCSVOutput
338// function. The sigScript is a trivial push of OP_TRUE followed by the
339// redeemScript to pass P2SH evaluation.
340func spendCSVOutput(redeemScript []byte, csvUTXO *wire.OutPoint,
341	sequence uint32, targetOutput *wire.TxOut,
342	txVersion int32) (*wire.MsgTx, error) {
343
344	tx := wire.NewMsgTx(txVersion)
345	tx.AddTxIn(&wire.TxIn{
346		PreviousOutPoint: *csvUTXO,
347		Sequence:         sequence,
348	})
349	tx.AddTxOut(targetOutput)
350
351	b := txscript.NewScriptBuilder().
352		AddOp(txscript.OP_TRUE).
353		AddData(redeemScript)
354
355	sigScript, err := b.Script()
356	if err != nil {
357		return nil, err
358	}
359	tx.TxIn[0].SignatureScript = sigScript
360
361	return tx, nil
362}
363
364// assertTxInBlock asserts a transaction with the specified txid is found
365// within the block with the passed block hash.
366func assertTxInBlock(r *rpctest.Harness, t *testing.T, blockHash *chainhash.Hash,
367	txid *chainhash.Hash) {
368
369	block, err := r.Node.GetBlock(blockHash)
370	if err != nil {
371		t.Fatalf("unable to get block: %v", err)
372	}
373	if len(block.Transactions) < 2 {
374		t.Fatal("target transaction was not mined")
375	}
376
377	for _, txn := range block.Transactions {
378		txHash := txn.TxHash()
379		if txn.TxHash() == txHash {
380			return
381		}
382	}
383
384	_, _, line, _ := runtime.Caller(1)
385	t.Fatalf("assertion failed at line %v: txid %v was not found in "+
386		"block %v", line, txid, blockHash)
387}
388
389// TestBIP0068AndBIP0112Activation tests for the proper adherence to the BIP
390// 112 and BIP 68 rule-set after the activation of the CSV-package soft-fork.
391//
392// Overview:
393//  - Pre soft-fork:
394//    - A transaction spending a CSV output validly should be rejected from the
395//    mempool, but accepted in a valid generated block including the
396//    transaction.
397//  - Post soft-fork:
398//    - See the cases exercised within the table driven tests towards the end
399//    of this test.
400func TestBIP0068AndBIP0112Activation(t *testing.T) {
401	t.Parallel()
402
403	// We'd like the test proper evaluation and validation of the BIP 68
404	// (sequence locks) and BIP 112 rule-sets which add input-age based
405	// relative lock times.
406
407	btcdCfg := []string{"--rejectnonstd"}
408	r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg)
409	if err != nil {
410		t.Fatal("unable to create primary harness: ", err)
411	}
412	if err := r.SetUp(true, 1); err != nil {
413		t.Fatalf("unable to setup test chain: %v", err)
414	}
415	defer r.TearDown()
416
417	assertSoftForkStatus(r, t, csvKey, blockchain.ThresholdStarted)
418
419	harnessAddr, err := r.NewAddress()
420	if err != nil {
421		t.Fatalf("unable to obtain harness address: %v", err)
422	}
423	harnessScript, err := txscript.PayToAddrScript(harnessAddr)
424	if err != nil {
425		t.Fatalf("unable to generate pkScript: %v", err)
426	}
427
428	const (
429		outputAmt         = btcutil.SatoshiPerBitcoin
430		relativeBlockLock = 10
431	)
432
433	sweepOutput := &wire.TxOut{
434		Value:    outputAmt - 5000,
435		PkScript: harnessScript,
436	}
437
438	// As the soft-fork hasn't yet activated _any_ transaction version
439	// which uses the CSV opcode should be accepted. Since at this point,
440	// CSV doesn't actually exist, it's just a NOP.
441	for txVersion := int32(0); txVersion < 3; txVersion++ {
442		// Create a trivially spendable output with a CSV lock-time of
443		// 10 relative blocks.
444		redeemScript, testUTXO, tx, err := createCSVOutput(r, t, outputAmt,
445			relativeBlockLock, false)
446		if err != nil {
447			t.Fatalf("unable to create CSV encumbered output: %v", err)
448		}
449
450		// As the transaction is p2sh it should be accepted into the
451		// mempool and found within the next generated block.
452		if _, err := r.Node.SendRawTransaction(tx, true); err != nil {
453			t.Fatalf("unable to broadcast tx: %v", err)
454		}
455		blocks, err := r.Node.Generate(1)
456		if err != nil {
457			t.Fatalf("unable to generate blocks: %v", err)
458		}
459		txid := tx.TxHash()
460		assertTxInBlock(r, t, blocks[0], &txid)
461
462		// Generate a custom transaction which spends the CSV output.
463		sequenceNum := blockchain.LockTimeToSequence(false, 10)
464		spendingTx, err := spendCSVOutput(redeemScript, testUTXO,
465			sequenceNum, sweepOutput, txVersion)
466		if err != nil {
467			t.Fatalf("unable to spend csv output: %v", err)
468		}
469
470		// This transaction should be rejected from the mempool since
471		// CSV validation is already mempool policy pre-fork.
472		_, err = r.Node.SendRawTransaction(spendingTx, true)
473		if err == nil {
474			t.Fatalf("transaction should have been rejected, but was " +
475				"instead accepted")
476		}
477
478		// However, this transaction should be accepted in a custom
479		// generated block as CSV validation for scripts within blocks
480		// shouldn't yet be active.
481		txns := []*btcutil.Tx{btcutil.NewTx(spendingTx)}
482		block, err := r.GenerateAndSubmitBlock(txns, -1, time.Time{})
483		if err != nil {
484			t.Fatalf("unable to submit block: %v", err)
485		}
486		txid = spendingTx.TxHash()
487		assertTxInBlock(r, t, block.Hash(), &txid)
488	}
489
490	// At this point, the block height should be 107: we started at height
491	// 101, then generated 2 blocks in each loop iteration above.
492	assertChainHeight(r, t, 107)
493
494	// With the height at 107 we need 200 blocks to be mined after the
495	// genesis target period, so we mine 192 blocks. This'll put us at
496	// height 299. The getblockchaininfo call checks the state for the
497	// block AFTER the current height.
498	numBlocks := (r.ActiveNet.MinerConfirmationWindow * 2) - 8
499	if _, err := r.Node.Generate(numBlocks); err != nil {
500		t.Fatalf("unable to generate blocks: %v", err)
501	}
502
503	assertChainHeight(r, t, 299)
504	assertSoftForkStatus(r, t, csvKey, blockchain.ThresholdActive)
505
506	// Knowing the number of outputs needed for the tests below, create a
507	// fresh output for use within each of the test-cases below.
508	const relativeTimeLock = 512
509	const numTests = 8
510	type csvOutput struct {
511		RedeemScript []byte
512		Utxo         *wire.OutPoint
513		Timelock     int32
514	}
515	var spendableInputs [numTests]csvOutput
516
517	// Create three outputs which have a block-based sequence locks, and
518	// three outputs which use the above time based sequence lock.
519	for i := 0; i < numTests; i++ {
520		timeLock := relativeTimeLock
521		isSeconds := true
522		if i < 7 {
523			timeLock = relativeBlockLock
524			isSeconds = false
525		}
526
527		redeemScript, utxo, tx, err := createCSVOutput(r, t, outputAmt,
528			int32(timeLock), isSeconds)
529		if err != nil {
530			t.Fatalf("unable to create CSV output: %v", err)
531		}
532
533		if _, err := r.Node.SendRawTransaction(tx, true); err != nil {
534			t.Fatalf("unable to broadcast transaction: %v", err)
535		}
536
537		spendableInputs[i] = csvOutput{
538			RedeemScript: redeemScript,
539			Utxo:         utxo,
540			Timelock:     int32(timeLock),
541		}
542	}
543
544	// Mine a single block including all the transactions generated above.
545	if _, err := r.Node.Generate(1); err != nil {
546		t.Fatalf("unable to generate block: %v", err)
547	}
548
549	// Now mine 10 additional blocks giving the inputs generated above a
550	// age of 11. Space out each block 10 minutes after the previous block.
551	prevBlockHash, err := r.Node.GetBestBlockHash()
552	if err != nil {
553		t.Fatalf("unable to get prior block hash: %v", err)
554	}
555	prevBlock, err := r.Node.GetBlock(prevBlockHash)
556	if err != nil {
557		t.Fatalf("unable to get block: %v", err)
558	}
559	for i := 0; i < relativeBlockLock; i++ {
560		timeStamp := prevBlock.Header.Timestamp.Add(time.Minute * 10)
561		b, err := r.GenerateAndSubmitBlock(nil, -1, timeStamp)
562		if err != nil {
563			t.Fatalf("unable to generate block: %v", err)
564		}
565
566		prevBlock = b.MsgBlock()
567	}
568
569	// A helper function to create fully signed transactions in-line during
570	// the array initialization below.
571	var inputIndex uint32
572	makeTxCase := func(sequenceNum uint32, txVersion int32) *wire.MsgTx {
573		csvInput := spendableInputs[inputIndex]
574
575		tx, err := spendCSVOutput(csvInput.RedeemScript, csvInput.Utxo,
576			sequenceNum, sweepOutput, txVersion)
577		if err != nil {
578			t.Fatalf("unable to spend CSV output: %v", err)
579		}
580
581		inputIndex++
582		return tx
583	}
584
585	tests := [numTests]struct {
586		tx     *wire.MsgTx
587		accept bool
588	}{
589		// A valid transaction with a single input a sequence number
590		// creating a 100 block relative time-lock. This transaction
591		// should be rejected as its version number is 1, and only tx
592		// of version > 2 will trigger the CSV behavior.
593		{
594			tx:     makeTxCase(blockchain.LockTimeToSequence(false, 100), 1),
595			accept: false,
596		},
597		// A transaction of version 2 spending a single input. The
598		// input has a relative time-lock of 1 block, but the disable
599		// bit it set. The transaction should be rejected as a result.
600		{
601			tx: makeTxCase(
602				blockchain.LockTimeToSequence(false, 1)|wire.SequenceLockTimeDisabled,
603				2,
604			),
605			accept: false,
606		},
607		// A v2 transaction with a single input having a 9 block
608		// relative time lock. The referenced input is 11 blocks old,
609		// but the CSV output requires a 10 block relative lock-time.
610		// Therefore, the transaction should be rejected.
611		{
612			tx:     makeTxCase(blockchain.LockTimeToSequence(false, 9), 2),
613			accept: false,
614		},
615		// A v2 transaction with a single input having a 10 block
616		// relative time lock. The referenced input is 11 blocks old so
617		// the transaction should be accepted.
618		{
619			tx:     makeTxCase(blockchain.LockTimeToSequence(false, 10), 2),
620			accept: true,
621		},
622		// A v2 transaction with a single input having a 11 block
623		// relative time lock. The input referenced has an input age of
624		// 11 and the CSV op-code requires 10 blocks to have passed, so
625		// this transaction should be accepted.
626		{
627			tx:     makeTxCase(blockchain.LockTimeToSequence(false, 11), 2),
628			accept: true,
629		},
630		// A v2 transaction whose input has a 1000 blck relative time
631		// lock.  This should be rejected as the input's age is only 11
632		// blocks.
633		{
634			tx:     makeTxCase(blockchain.LockTimeToSequence(false, 1000), 2),
635			accept: false,
636		},
637		// A v2 transaction with a single input having a 512,000 second
638		// relative time-lock. This transaction should be rejected as 6
639		// days worth of blocks haven't yet been mined. The referenced
640		// input doesn't have sufficient age.
641		{
642			tx:     makeTxCase(blockchain.LockTimeToSequence(true, 512000), 2),
643			accept: false,
644		},
645		// A v2 transaction whose single input has a 512 second
646		// relative time-lock. This transaction should be accepted as
647		// finalized.
648		{
649			tx:     makeTxCase(blockchain.LockTimeToSequence(true, 512), 2),
650			accept: true,
651		},
652	}
653
654	for i, test := range tests {
655		txid, err := r.Node.SendRawTransaction(test.tx, true)
656		switch {
657		// Test case passes, nothing further to report.
658		case test.accept && err == nil:
659
660		// Transaction should have been accepted but we have a non-nil
661		// error.
662		case test.accept && err != nil:
663			t.Fatalf("test #%d, transaction should be accepted, "+
664				"but was rejected: %v", i, err)
665
666		// Transaction should have been rejected, but it was accepted.
667		case !test.accept && err == nil:
668			t.Fatalf("test #%d, transaction should be rejected, "+
669				"but was accepted", i)
670
671		// Transaction was rejected as wanted, nothing more to do.
672		case !test.accept && err != nil:
673		}
674
675		// If the transaction should be rejected, manually mine a block
676		// with the non-final transaction. It should be rejected.
677		if !test.accept {
678			txns := []*btcutil.Tx{btcutil.NewTx(test.tx)}
679			_, err := r.GenerateAndSubmitBlock(txns, -1, time.Time{})
680			if err == nil {
681				t.Fatalf("test #%d, invalid block accepted", i)
682			}
683
684			continue
685		}
686
687		// Generate a block, the transaction should be included within
688		// the newly mined block.
689		blockHashes, err := r.Node.Generate(1)
690		if err != nil {
691			t.Fatalf("unable to mine block: %v", err)
692		}
693		assertTxInBlock(r, t, blockHashes[0], txid)
694	}
695}
696