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