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.
4
5package bloom_test
6
7import (
8	"bytes"
9	"encoding/hex"
10	"testing"
11
12	"github.com/btcsuite/btcd/chaincfg/chainhash"
13	"github.com/btcsuite/btcd/wire"
14	"github.com/btcsuite/btcutil"
15	"github.com/btcsuite/btcutil/bloom"
16)
17
18// TestFilterLarge ensures a maximum sized filter can be created.
19func TestFilterLarge(t *testing.T) {
20	f := bloom.NewFilter(100000000, 0, 0.01, wire.BloomUpdateNone)
21	if len(f.MsgFilterLoad().Filter) > wire.MaxFilterLoadFilterSize {
22		t.Errorf("TestFilterLarge test failed: %d > %d",
23			len(f.MsgFilterLoad().Filter), wire.MaxFilterLoadFilterSize)
24	}
25}
26
27// TestFilterLoad ensures loading and unloading of a filter pass.
28func TestFilterLoad(t *testing.T) {
29	merkle := wire.MsgFilterLoad{}
30
31	f := bloom.LoadFilter(&merkle)
32	if !f.IsLoaded() {
33		t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v",
34			true, !f.IsLoaded())
35		return
36	}
37	f.Unload()
38	if f.IsLoaded() {
39		t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v",
40			f.IsLoaded(), false)
41		return
42	}
43}
44
45// TestFilterInsert ensures inserting data into the filter causes that data
46// to be matched and the resulting serialized MsgFilterLoad is the expected
47// value.
48func TestFilterInsert(t *testing.T) {
49	var tests = []struct {
50		hex    string
51		insert bool
52	}{
53		{"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true},
54		{"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false},
55		{"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true},
56		{"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true},
57	}
58
59	f := bloom.NewFilter(3, 0, 0.01, wire.BloomUpdateAll)
60
61	for i, test := range tests {
62		data, err := hex.DecodeString(test.hex)
63		if err != nil {
64			t.Errorf("TestFilterInsert DecodeString failed: %v\n", err)
65			return
66		}
67		if test.insert {
68			f.Add(data)
69		}
70
71		result := f.Matches(data)
72		if test.insert != result {
73			t.Errorf("TestFilterInsert Matches test #%d failure: got %v want %v\n",
74				i, result, test.insert)
75			return
76		}
77	}
78
79	want, err := hex.DecodeString("03614e9b050000000000000001")
80	if err != nil {
81		t.Errorf("TestFilterInsert DecodeString failed: %v\n", err)
82		return
83	}
84
85	got := bytes.NewBuffer(nil)
86	err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding)
87	if err != nil {
88		t.Errorf("TestFilterInsert BtcDecode failed: %v\n", err)
89		return
90	}
91
92	if !bytes.Equal(got.Bytes(), want) {
93		t.Errorf("TestFilterInsert failure: got %v want %v\n",
94			got.Bytes(), want)
95		return
96	}
97}
98
99// TestFilterFPRange checks that new filters made with out of range
100// false positive targets result in either max or min false positive rates.
101func TestFilterFPRange(t *testing.T) {
102	tests := []struct {
103		name   string
104		hash   string
105		want   string
106		filter *bloom.Filter
107	}{
108		{
109			name:   "fprates > 1 should be clipped at 1",
110			hash:   "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
111			want:   "00000000000000000001",
112			filter: bloom.NewFilter(1, 0, 20.9999999769, wire.BloomUpdateAll),
113		},
114		{
115			name:   "fprates less than 1e-9 should be clipped at min",
116			hash:   "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
117			want:   "0566d97a91a91b0000000000000001",
118			filter: bloom.NewFilter(1, 0, 0, wire.BloomUpdateAll),
119		},
120		{
121			name:   "negative fprates should be clipped at min",
122			hash:   "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
123			want:   "0566d97a91a91b0000000000000001",
124			filter: bloom.NewFilter(1, 0, -1, wire.BloomUpdateAll),
125		},
126	}
127
128	for _, test := range tests {
129		// Convert test input to appropriate types.
130		hash, err := chainhash.NewHashFromStr(test.hash)
131		if err != nil {
132			t.Errorf("NewHashFromStr unexpected error: %v", err)
133			continue
134		}
135		want, err := hex.DecodeString(test.want)
136		if err != nil {
137			t.Errorf("DecodeString unexpected error: %v\n", err)
138			continue
139		}
140
141		// Add the test hash to the bloom filter and ensure the
142		// filter serializes to the expected bytes.
143		f := test.filter
144		f.AddHash(hash)
145		got := bytes.NewBuffer(nil)
146		err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding)
147		if err != nil {
148			t.Errorf("BtcDecode unexpected error: %v\n", err)
149			continue
150		}
151		if !bytes.Equal(got.Bytes(), want) {
152			t.Errorf("serialized filter mismatch: got %x want %x\n",
153				got.Bytes(), want)
154			continue
155		}
156	}
157}
158
159// TestFilterInsert ensures inserting data into the filter with a tweak causes
160// that data to be matched and the resulting serialized MsgFilterLoad is the
161// expected value.
162func TestFilterInsertWithTweak(t *testing.T) {
163	var tests = []struct {
164		hex    string
165		insert bool
166	}{
167		{"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true},
168		{"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false},
169		{"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true},
170		{"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true},
171	}
172
173	f := bloom.NewFilter(3, 2147483649, 0.01, wire.BloomUpdateAll)
174
175	for i, test := range tests {
176		data, err := hex.DecodeString(test.hex)
177		if err != nil {
178			t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
179			return
180		}
181		if test.insert {
182			f.Add(data)
183		}
184
185		result := f.Matches(data)
186		if test.insert != result {
187			t.Errorf("TestFilterInsertWithTweak Matches test #%d failure: got %v want %v\n",
188				i, result, test.insert)
189			return
190		}
191	}
192
193	want, err := hex.DecodeString("03ce4299050000000100008001")
194	if err != nil {
195		t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
196		return
197	}
198	got := bytes.NewBuffer(nil)
199	err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding)
200	if err != nil {
201		t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err)
202		return
203	}
204
205	if !bytes.Equal(got.Bytes(), want) {
206		t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n",
207			got.Bytes(), want)
208		return
209	}
210}
211
212// TestFilterInsertKey ensures inserting public keys and addresses works as
213// expected.
214func TestFilterInsertKey(t *testing.T) {
215	secret := "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"
216
217	wif, err := btcutil.DecodeWIF(secret)
218	if err != nil {
219		t.Errorf("TestFilterInsertKey DecodeWIF failed: %v", err)
220		return
221	}
222
223	f := bloom.NewFilter(2, 0, 0.001, wire.BloomUpdateAll)
224	f.Add(wif.SerializePubKey())
225	f.Add(btcutil.Hash160(wif.SerializePubKey()))
226
227	want, err := hex.DecodeString("038fc16b080000000000000001")
228	if err != nil {
229		t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
230		return
231	}
232	got := bytes.NewBuffer(nil)
233	err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding)
234	if err != nil {
235		t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err)
236		return
237	}
238
239	if !bytes.Equal(got.Bytes(), want) {
240		t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n",
241			got.Bytes(), want)
242		return
243	}
244}
245
246func TestFilterBloomMatch(t *testing.T) {
247	str := "01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e" +
248		"88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7" +
249		"c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d2" +
250		"7d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee" +
251		"51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5e" +
252		"eef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c33" +
253		"9ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3" +
254		"bc6e2754dbcff1988ac2f15de00000000001976a914a266436d296554760" +
255		"8b9e15d9032a7b9d64fa43188ac00000000"
256	strBytes, err := hex.DecodeString(str)
257	if err != nil {
258		t.Errorf("TestFilterBloomMatch DecodeString failure: %v", err)
259		return
260	}
261	tx, err := btcutil.NewTxFromBytes(strBytes)
262	if err != nil {
263		t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err)
264		return
265	}
266	spendingTxBytes := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f,
267		0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6,
268		0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27,
269		0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f,
270		0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30,
271		0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce,
272		0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57,
273		0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0,
274		0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c,
275		0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00,
276		0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e,
277		0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27,
278		0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01,
279		0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10,
280		0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9,
281		0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5,
282		0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff,
283		0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf,
284		0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9,
285		0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb,
286		0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b,
287		0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76,
288		0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07,
289		0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0,
290		0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8,
291		0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14,
292		0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51,
293		0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70,
294		0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00}
295
296	spendingTx, err := btcutil.NewTxFromBytes(spendingTxBytes)
297	if err != nil {
298		t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err)
299		return
300	}
301
302	f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
303	inputStr := "b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"
304	hash, err := chainhash.NewHashFromStr(inputStr)
305	if err != nil {
306		t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
307		return
308	}
309	f.AddHash(hash)
310	if !f.MatchTxAndUpdate(tx) {
311		t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr)
312	}
313
314	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
315	inputStr = "6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"
316	hashBytes, err := hex.DecodeString(inputStr)
317	if err != nil {
318		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
319		return
320	}
321	f.Add(hashBytes)
322	if !f.MatchTxAndUpdate(tx) {
323		t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr)
324	}
325
326	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
327	inputStr = "30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065" +
328		"f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643" +
329		"ac4cb7cb3c462aced7f14711a01"
330	hashBytes, err = hex.DecodeString(inputStr)
331	if err != nil {
332		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
333		return
334	}
335	f.Add(hashBytes)
336	if !f.MatchTxAndUpdate(tx) {
337		t.Errorf("TestFilterBloomMatch didn't match input signature %s", inputStr)
338	}
339
340	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
341	inputStr = "046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95" +
342		"c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe" +
343		"76036c339"
344	hashBytes, err = hex.DecodeString(inputStr)
345	if err != nil {
346		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
347		return
348	}
349	f.Add(hashBytes)
350	if !f.MatchTxAndUpdate(tx) {
351		t.Errorf("TestFilterBloomMatch didn't match input pubkey %s", inputStr)
352	}
353
354	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
355	inputStr = "04943fdd508053c75000106d3bc6e2754dbcff19"
356	hashBytes, err = hex.DecodeString(inputStr)
357	if err != nil {
358		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
359		return
360	}
361	f.Add(hashBytes)
362	if !f.MatchTxAndUpdate(tx) {
363		t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr)
364	}
365	if !f.MatchTxAndUpdate(spendingTx) {
366		t.Errorf("TestFilterBloomMatch spendingTx didn't match output address %s", inputStr)
367	}
368
369	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
370	inputStr = "a266436d2965547608b9e15d9032a7b9d64fa431"
371	hashBytes, err = hex.DecodeString(inputStr)
372	if err != nil {
373		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
374		return
375	}
376	f.Add(hashBytes)
377	if !f.MatchTxAndUpdate(tx) {
378		t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr)
379	}
380
381	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
382	inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
383	hash, err = chainhash.NewHashFromStr(inputStr)
384	if err != nil {
385		t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
386		return
387	}
388	outpoint := wire.NewOutPoint(hash, 0)
389	f.AddOutPoint(outpoint)
390	if !f.MatchTxAndUpdate(tx) {
391		t.Errorf("TestFilterBloomMatch didn't match outpoint %s", inputStr)
392	}
393
394	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
395	inputStr = "00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"
396	hash, err = chainhash.NewHashFromStr(inputStr)
397	if err != nil {
398		t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
399		return
400	}
401	f.AddHash(hash)
402	if f.MatchTxAndUpdate(tx) {
403		t.Errorf("TestFilterBloomMatch matched hash %s", inputStr)
404	}
405
406	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
407	inputStr = "0000006d2965547608b9e15d9032a7b9d64fa431"
408	hashBytes, err = hex.DecodeString(inputStr)
409	if err != nil {
410		t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
411		return
412	}
413	f.Add(hashBytes)
414	if f.MatchTxAndUpdate(tx) {
415		t.Errorf("TestFilterBloomMatch matched address %s", inputStr)
416	}
417
418	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
419	inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
420	hash, err = chainhash.NewHashFromStr(inputStr)
421	if err != nil {
422		t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
423		return
424	}
425	outpoint = wire.NewOutPoint(hash, 1)
426	f.AddOutPoint(outpoint)
427	if f.MatchTxAndUpdate(tx) {
428		t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr)
429	}
430
431	f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
432	inputStr = "000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
433	hash, err = chainhash.NewHashFromStr(inputStr)
434	if err != nil {
435		t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
436		return
437	}
438	outpoint = wire.NewOutPoint(hash, 0)
439	f.AddOutPoint(outpoint)
440	if f.MatchTxAndUpdate(tx) {
441		t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr)
442	}
443}
444
445func TestFilterInsertUpdateNone(t *testing.T) {
446	f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateNone)
447
448	// Add the generation pubkey
449	inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" +
450		"876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" +
451		"2252247d97a46a91"
452	inputBytes, err := hex.DecodeString(inputStr)
453	if err != nil {
454		t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err)
455		return
456	}
457	f.Add(inputBytes)
458
459	// Add the output address for the 4th transaction
460	inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21"
461	inputBytes, err = hex.DecodeString(inputStr)
462	if err != nil {
463		t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err)
464		return
465	}
466	f.Add(inputBytes)
467
468	inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"
469	hash, err := chainhash.NewHashFromStr(inputStr)
470	if err != nil {
471		t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err)
472		return
473	}
474	outpoint := wire.NewOutPoint(hash, 0)
475
476	if f.MatchesOutPoint(outpoint) {
477		t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr)
478		return
479	}
480
481	inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"
482	hash, err = chainhash.NewHashFromStr(inputStr)
483	if err != nil {
484		t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err)
485		return
486	}
487	outpoint = wire.NewOutPoint(hash, 0)
488
489	if f.MatchesOutPoint(outpoint) {
490		t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr)
491		return
492	}
493}
494
495func TestFilterInsertP2PubKeyOnly(t *testing.T) {
496	blockStr := "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc" +
497		"880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367" +
498		"117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010" +
499		"00000000000000000000000000000000000000000000000000000000000" +
500		"0000ffffffff07044c86041b0136ffffffff0100f2052a0100000043410" +
501		"4eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2" +
502		"c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a22522" +
503		"47d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255" +
504		"120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356" +
505		"e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062e" +
506		"a10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa" +
507		"608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ec" +
508		"bba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141" +
509		"b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac0000000001000000" +
510		"03fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26a" +
511		"f16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23" +
512		"b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6" +
513		"b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e" +
514		"29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245b" +
515		"d69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585" +
516		"caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e7" +
517		"5429df397b5af83000000004948304502202bdb79c596a9ffc24e96f438" +
518		"6199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b72" +
519		"4fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffff" +
520		"ff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cb" +
521		"cb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9cecc" +
522		"d328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f11" +
523		"87779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff010071" +
524		"4460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8" +
525		"d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397" +
526		"cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3" +
527		"e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e4022100" +
528		"8581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7" +
529		"c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf64852" +
530		"61c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d" +
531		"3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f2" +
532		"48e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124" +
533		"c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93" +
534		"0220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346" +
535		"669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6" +
536		"485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270e" +
537		"fb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051" +
538		"fd372bb7a537232946e0a46f53636b4dafdaa4000000008c49304602210" +
539		"0c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de" +
540		"35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46f" +
541		"c37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0" +
542		"f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f" +
543		"4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f8" +
544		"94aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493" +
545		"046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8a" +
546		"a788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415" +
547		"588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb" +
548		"7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018" +
549		"ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8" +
550		"040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188a" +
551		"c000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" +
552		"f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34" +
553		"fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243" +
554		"bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec" +
555		"20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442" +
556		"e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632" +
557		"d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10" +
558		"eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a91" +
559		"4a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000" +
560		"000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850" +
561		"927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec" +
562		"2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a25" +
563		"7b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e5" +
564		"21fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455f" +
565		"e30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098" +
566		"544bffffffff0240420f00000000001976a9144676d1b820d63ec272f19" +
567		"00d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00" +
568		"d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc91750" +
569		"1ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f10000" +
570		"00008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e" +
571		"280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba80" +
572		"7892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b" +
573		"5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c4" +
574		"7d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41e" +
575		"d70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d0" +
576		"68000000008b4830450221008513ad65187b903aed1102d1d0c47688127" +
577		"658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de6603" +
578		"5fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50b" +
579		"e1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b0682" +
580		"0edca9ef982c35fda2d255afba340068c5035552368bc7200c1488fffff" +
581		"fff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e40" +
582		"0f8699eb4888ac00000000"
583	blockBytes, err := hex.DecodeString(blockStr)
584	if err != nil {
585		t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
586		return
587	}
588	block, err := btcutil.NewBlockFromBytes(blockBytes)
589	if err != nil {
590		t.Errorf("TestFilterInsertP2PubKeyOnly NewBlockFromBytes failed: %v", err)
591		return
592	}
593
594	f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateP2PubkeyOnly)
595
596	// Generation pubkey
597	inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" +
598		"876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" +
599		"2252247d97a46a91"
600	inputBytes, err := hex.DecodeString(inputStr)
601	if err != nil {
602		t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
603		return
604	}
605	f.Add(inputBytes)
606
607	// Output address of 4th transaction
608	inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21"
609	inputBytes, err = hex.DecodeString(inputStr)
610	if err != nil {
611		t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
612		return
613	}
614	f.Add(inputBytes)
615
616	// Ignore return value -- this is just used to update the filter.
617	_, _ = bloom.NewMerkleBlock(block, f)
618
619	// We should match the generation pubkey
620	inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"
621	hash, err := chainhash.NewHashFromStr(inputStr)
622	if err != nil {
623		t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err)
624		return
625	}
626	outpoint := wire.NewOutPoint(hash, 0)
627	if !f.MatchesOutPoint(outpoint) {
628		t.Errorf("TestMerkleBlockP2PubKeyOnly didn't match the generation "+
629			"outpoint %s", inputStr)
630		return
631	}
632
633	// We should not match the 4th transaction, which is not p2pk
634	inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"
635	hash, err = chainhash.NewHashFromStr(inputStr)
636	if err != nil {
637		t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err)
638		return
639	}
640	outpoint = wire.NewOutPoint(hash, 0)
641	if f.MatchesOutPoint(outpoint) {
642		t.Errorf("TestMerkleBlockP2PubKeyOnly matched outpoint %s", inputStr)
643		return
644	}
645}
646
647func TestFilterReload(t *testing.T) {
648	f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
649
650	bFilter := bloom.LoadFilter(f.MsgFilterLoad())
651	if bFilter.MsgFilterLoad() == nil {
652		t.Errorf("TestFilterReload LoadFilter test failed")
653		return
654	}
655	bFilter.Reload(nil)
656
657	if bFilter.MsgFilterLoad() != nil {
658		t.Errorf("TestFilterReload Reload test failed")
659	}
660}
661