1 // Copyright (c) 2013-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.
12 "github.com/btcsuite/btcd/btcec"
13 "github.com/btcsuite/btcd/chaincfg"
14 "github.com/btcsuite/btcd/chaincfg/chainhash"
15 "github.com/btcsuite/btcd/txscript"
16 "github.com/btcsuite/btcd/wire"
17 "github.com/btcsuite/btcutil"
20 // TestCalcMinRequiredTxRelayFee tests the calcMinRequiredTxRelayFee API.
21 func TestCalcMinRequiredTxRelayFee(t *testing.T) {
23 name string // test description.
24 size int64 // Transaction size in bytes.
25 relayFee btcutil.Amount // minimum relay transaction fee.
26 want int64 // Expected fee.
29 // Ensure combination of size and fee that are less than 1000
30 // produce a non-zero fee.
31 "250 bytes with relay fee of 3",
37 "100 bytes with default minimum relay fee",
43 "max standard tx size with default minimum relay fee",
44 maxStandardTxWeight / 4,
49 "max standard tx size with max satoshi relay fee",
50 maxStandardTxWeight / 4,
55 "1500 bytes with 5000 relay fee",
61 "1500 bytes with 3000 relay fee",
67 "782 bytes with 5000 relay fee",
73 "782 bytes with 3000 relay fee",
79 "782 bytes with 2550 relay fee",
86 for _, test := range tests {
87 got := calcMinRequiredTxRelayFee(test.size, test.relayFee)
89 t.Errorf("TestCalcMinRequiredTxRelayFee test '%s' "+
90 "failed: got %v want %v", test.name, got,
97 // TestCheckPkScriptStandard tests the checkPkScriptStandard API.
98 func TestCheckPkScriptStandard(t *testing.T) {
100 for i := 0; i < 4; i++ {
101 pk, err := btcec.NewPrivateKey(btcec.S256())
103 t.Fatalf("TestCheckPkScriptStandard NewPrivateKey failed: %v",
107 pubKeys = append(pubKeys, pk.PubKey().SerializeCompressed())
111 name string // test description.
112 script *txscript.ScriptBuilder
117 txscript.NewScriptBuilder().AddOp(txscript.OP_2).
118 AddData(pubKeys[0]).AddData(pubKeys[1]).
119 AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG),
124 txscript.NewScriptBuilder().AddOp(txscript.OP_1).
125 AddData(pubKeys[0]).AddData(pubKeys[1]).
126 AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG),
131 txscript.NewScriptBuilder().AddOp(txscript.OP_2).
132 AddData(pubKeys[0]).AddData(pubKeys[1]).
134 AddOp(txscript.OP_3).AddOp(txscript.OP_CHECKMULTISIG),
139 txscript.NewScriptBuilder().AddOp(txscript.OP_1).
140 AddData(pubKeys[0]).AddData(pubKeys[1]).
141 AddData(pubKeys[2]).AddData(pubKeys[3]).
142 AddOp(txscript.OP_4).AddOp(txscript.OP_CHECKMULTISIG),
147 txscript.NewScriptBuilder().AddOp(txscript.OP_3).
148 AddData(pubKeys[0]).AddData(pubKeys[1]).
149 AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG),
154 txscript.NewScriptBuilder().AddOp(txscript.OP_2).
155 AddData(pubKeys[0]).AddData(pubKeys[1]).
156 AddOp(txscript.OP_3).AddOp(txscript.OP_CHECKMULTISIG),
161 txscript.NewScriptBuilder().AddOp(txscript.OP_0).
162 AddData(pubKeys[0]).AddData(pubKeys[1]).
163 AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG),
168 txscript.NewScriptBuilder().AddOp(txscript.OP_1).
169 AddData(pubKeys[0]).AddData(pubKeys[1]).
170 AddOp(txscript.OP_0).AddOp(txscript.OP_CHECKMULTISIG),
175 txscript.NewScriptBuilder().AddOp(txscript.OP_1).
176 AddData(pubKeys[0]).AddData(pubKeys[1]).
177 AddOp(txscript.OP_CHECKMULTISIG),
182 txscript.NewScriptBuilder().AddOp(txscript.OP_1).
183 AddData(pubKeys[0]).AddData(pubKeys[1]),
188 for _, test := range tests {
189 script, err := test.script.Script()
191 t.Fatalf("TestCheckPkScriptStandard test '%s' "+
192 "failed: %v", test.name, err)
195 scriptClass := txscript.GetScriptClass(script)
196 got := checkPkScriptStandard(script, scriptClass)
197 if (test.isStandard && got != nil) ||
198 (!test.isStandard && got == nil) {
200 t.Fatalf("TestCheckPkScriptStandard test '%s' failed",
207 // TestDust tests the isDust API.
208 func TestDust(t *testing.T) {
209 pkScript := []byte{0x76, 0xa9, 0x21, 0x03, 0x2f, 0x7e, 0x43,
210 0x0a, 0xa4, 0xc9, 0xd1, 0x59, 0x43, 0x7e, 0x84, 0xb9,
211 0x75, 0xdc, 0x76, 0xd9, 0x00, 0x3b, 0xf0, 0x92, 0x2c,
212 0xf3, 0xaa, 0x45, 0x28, 0x46, 0x4b, 0xab, 0x78, 0x0d,
213 0xba, 0x5e, 0x88, 0xac}
216 name string // test description
218 relayFee btcutil.Amount // minimum relay transaction fee.
222 // Any value is allowed with a zero relay fee.
223 "zero value with zero relay fee",
224 wire.TxOut{Value: 0, PkScript: pkScript},
229 // Zero value is dust with any relay fee"
230 "zero value with very small tx fee",
231 wire.TxOut{Value: 0, PkScript: pkScript},
236 "38 byte public key script with value 584",
237 wire.TxOut{Value: 584, PkScript: pkScript},
242 "38 byte public key script with value 585",
243 wire.TxOut{Value: 585, PkScript: pkScript},
248 // Maximum allowed value is never dust.
249 "max satoshi amount is never dust",
250 wire.TxOut{Value: btcutil.MaxSatoshi, PkScript: pkScript},
255 // Maximum int64 value causes overflow.
256 "maximum int64 value",
257 wire.TxOut{Value: 1<<63 - 1, PkScript: pkScript},
262 // Unspendable pkScript due to an invalid public key
264 "unspendable pkScript",
265 wire.TxOut{Value: 5000, PkScript: []byte{0x01}},
270 for _, test := range tests {
271 res := isDust(&test.txOut, test.relayFee)
272 if res != test.isDust {
273 t.Fatalf("Dust test '%s' failed: want %v got %v",
274 test.name, test.isDust, res)
280 // TestCheckTransactionStandard tests the checkTransactionStandard API.
281 func TestCheckTransactionStandard(t *testing.T) {
282 // Create some dummy, but otherwise standard, data for transactions.
283 prevOutHash, err := chainhash.NewHashFromStr("01")
285 t.Fatalf("NewShaHashFromStr: unexpected error: %v", err)
287 dummyPrevOut := wire.OutPoint{Hash: *prevOutHash, Index: 1}
288 dummySigScript := bytes.Repeat([]byte{0x00}, 65)
289 dummyTxIn := wire.TxIn{
290 PreviousOutPoint: dummyPrevOut,
291 SignatureScript: dummySigScript,
292 Sequence: wire.MaxTxInSequenceNum,
294 addrHash := [20]byte{0x01}
295 addr, err := btcutil.NewAddressPubKeyHash(addrHash[:],
296 &chaincfg.TestNet3Params)
298 t.Fatalf("NewAddressPubKeyHash: unexpected error: %v", err)
300 dummyPkScript, err := txscript.PayToAddrScript(addr)
302 t.Fatalf("PayToAddrScript: unexpected error: %v", err)
304 dummyTxOut := wire.TxOut{
305 Value: 100000000, // 1 BTC
306 PkScript: dummyPkScript,
317 name: "Typical pay-to-pubkey-hash transaction",
320 TxIn: []*wire.TxIn{&dummyTxIn},
321 TxOut: []*wire.TxOut{&dummyTxOut},
328 name: "Transaction version too high",
330 Version: wire.TxVersion + 1,
331 TxIn: []*wire.TxIn{&dummyTxIn},
332 TxOut: []*wire.TxOut{&dummyTxOut},
337 code: wire.RejectNonstandard,
340 name: "Transaction is not finalized",
344 PreviousOutPoint: dummyPrevOut,
345 SignatureScript: dummySigScript,
348 TxOut: []*wire.TxOut{&dummyTxOut},
353 code: wire.RejectNonstandard,
356 name: "Transaction size is too large",
359 TxIn: []*wire.TxIn{&dummyTxIn},
360 TxOut: []*wire.TxOut{{
362 PkScript: bytes.Repeat([]byte{0x00},
363 (maxStandardTxWeight/4)+1),
369 code: wire.RejectNonstandard,
372 name: "Signature script size is too large",
376 PreviousOutPoint: dummyPrevOut,
377 SignatureScript: bytes.Repeat([]byte{0x00},
378 maxStandardSigScriptSize+1),
379 Sequence: wire.MaxTxInSequenceNum,
381 TxOut: []*wire.TxOut{&dummyTxOut},
386 code: wire.RejectNonstandard,
389 name: "Signature script that does more than push data",
393 PreviousOutPoint: dummyPrevOut,
394 SignatureScript: []byte{
395 txscript.OP_CHECKSIGVERIFY},
396 Sequence: wire.MaxTxInSequenceNum,
398 TxOut: []*wire.TxOut{&dummyTxOut},
403 code: wire.RejectNonstandard,
406 name: "Valid but non standard public key script",
409 TxIn: []*wire.TxIn{&dummyTxIn},
410 TxOut: []*wire.TxOut{{
412 PkScript: []byte{txscript.OP_TRUE},
418 code: wire.RejectNonstandard,
421 name: "More than one nulldata output",
424 TxIn: []*wire.TxIn{&dummyTxIn},
425 TxOut: []*wire.TxOut{{
427 PkScript: []byte{txscript.OP_RETURN},
430 PkScript: []byte{txscript.OP_RETURN},
436 code: wire.RejectNonstandard,
442 TxIn: []*wire.TxIn{&dummyTxIn},
443 TxOut: []*wire.TxOut{{
445 PkScript: dummyPkScript,
451 code: wire.RejectDust,
454 name: "One nulldata output with 0 amount (standard)",
457 TxIn: []*wire.TxIn{&dummyTxIn},
458 TxOut: []*wire.TxOut{{
460 PkScript: []byte{txscript.OP_RETURN},
469 pastMedianTime := time.Now()
470 for _, test := range tests {
471 // Ensure standardness is as expected.
472 err := checkTransactionStandard(btcutil.NewTx(&test.tx),
473 test.height, pastMedianTime, DefaultMinRelayTxFee, 1)
474 if err == nil && test.isStandard {
475 // Test passes since function returned standard for a
476 // transaction which is intended to be standard.
479 if err == nil && !test.isStandard {
480 t.Errorf("checkTransactionStandard (%s): standard when "+
481 "it should not be", test.name)
484 if err != nil && test.isStandard {
485 t.Errorf("checkTransactionStandard (%s): nonstandard "+
486 "when it should not be: %v", test.name, err)
490 // Ensure error type is a TxRuleError inside of a RuleError.
491 rerr, ok := err.(RuleError)
493 t.Errorf("checkTransactionStandard (%s): unexpected "+
494 "error type - got %T", test.name, err)
497 txrerr, ok := rerr.Err.(TxRuleError)
499 t.Errorf("checkTransactionStandard (%s): unexpected "+
500 "error type - got %T", test.name, rerr.Err)
504 // Ensure the reject code is the expected one.
505 if txrerr.RejectCode != test.code {
506 t.Errorf("checkTransactionStandard (%s): unexpected "+
507 "error code - got %v, want %v", test.name,
508 txrerr.RejectCode, test.code)