lbcutil/bloom/filter_test.go
Dave Collins 22c91fa80a Update for recent chainhash-related API changes. (#78)
This updates all code in the main package and subpackages to make use of
the new chainhash package since the old wire.ShaHash type and functions
have been removed in favor of the abstracted package.

Also, since this required API changes anyways and the hash algorithm is
no longer tied specifically to SHA, all other functions throughout the
code base which had "Sha" in their name have been changed to Hash so
they are not incorrectly implying the hash algorithm.

The following is an overview of the changes:

- Update all references to wire.ShaHash to the new chainhash.Hash type
- Rename the following functions and update all references:
  - Block.Sha -> Hash
  - Block.TxSha -> TxHash
  - Tx.Sha -> Hash
  - bloom.Filter.AddShaHash -> AddHash
- Rename all variables that included sha in their name to include hash
  instead
- Add license headers to coinset package files
2016-08-08 12:38:16 -05:00

660 lines
23 KiB
Go

// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package bloom_test
import (
"bytes"
"encoding/hex"
"testing"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/bloom"
)
// TestFilterLarge ensures a maximum sized filter can be created.
func TestFilterLarge(t *testing.T) {
f := bloom.NewFilter(100000000, 0, 0.01, wire.BloomUpdateNone)
if len(f.MsgFilterLoad().Filter) > wire.MaxFilterLoadFilterSize {
t.Errorf("TestFilterLarge test failed: %d > %d",
len(f.MsgFilterLoad().Filter), wire.MaxFilterLoadFilterSize)
}
}
// TestFilterLoad ensures loading and unloading of a filter pass.
func TestFilterLoad(t *testing.T) {
merkle := wire.MsgFilterLoad{}
f := bloom.LoadFilter(&merkle)
if !f.IsLoaded() {
t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v",
true, !f.IsLoaded())
return
}
f.Unload()
if f.IsLoaded() {
t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v",
f.IsLoaded(), false)
return
}
}
// TestFilterInsert ensures inserting data into the filter causes that data
// to be matched and the resulting serialized MsgFilterLoad is the expected
// value.
func TestFilterInsert(t *testing.T) {
var tests = []struct {
hex string
insert bool
}{
{"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true},
{"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false},
{"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true},
{"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true},
}
f := bloom.NewFilter(3, 0, 0.01, wire.BloomUpdateAll)
for i, test := range tests {
data, err := hex.DecodeString(test.hex)
if err != nil {
t.Errorf("TestFilterInsert DecodeString failed: %v\n", err)
return
}
if test.insert {
f.Add(data)
}
result := f.Matches(data)
if test.insert != result {
t.Errorf("TestFilterInsert Matches test #%d failure: got %v want %v\n",
i, result, test.insert)
return
}
}
want, err := hex.DecodeString("03614e9b050000000000000001")
if err != nil {
t.Errorf("TestFilterInsert DecodeString failed: %v\n", err)
return
}
got := bytes.NewBuffer(nil)
err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion)
if err != nil {
t.Errorf("TestFilterInsert BtcDecode failed: %v\n", err)
return
}
if !bytes.Equal(got.Bytes(), want) {
t.Errorf("TestFilterInsert failure: got %v want %v\n",
got.Bytes(), want)
return
}
}
// TestFilterFPRange checks that new filters made with out of range
// false positive targets result in either max or min false positive rates.
func TestFilterFPRange(t *testing.T) {
tests := []struct {
name string
hash string
want string
filter *bloom.Filter
}{
{
name: "fprates > 1 should be clipped at 1",
hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
want: "00000000000000000001",
filter: bloom.NewFilter(1, 0, 20.9999999769, wire.BloomUpdateAll),
},
{
name: "fprates less than 1e-9 should be clipped at min",
hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
want: "0566d97a91a91b0000000000000001",
filter: bloom.NewFilter(1, 0, 0, wire.BloomUpdateAll),
},
{
name: "negative fprates should be clipped at min",
hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041",
want: "0566d97a91a91b0000000000000001",
filter: bloom.NewFilter(1, 0, -1, wire.BloomUpdateAll),
},
}
for _, test := range tests {
// Convert test input to appropriate types.
hash, err := chainhash.NewHashFromStr(test.hash)
if err != nil {
t.Errorf("NewHashFromStr unexpected error: %v", err)
continue
}
want, err := hex.DecodeString(test.want)
if err != nil {
t.Errorf("DecodeString unexpected error: %v\n", err)
continue
}
// Add the test hash to the bloom filter and ensure the
// filter serializes to the expected bytes.
f := test.filter
f.AddHash(hash)
got := bytes.NewBuffer(nil)
err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion)
if err != nil {
t.Errorf("BtcDecode unexpected error: %v\n", err)
continue
}
if !bytes.Equal(got.Bytes(), want) {
t.Errorf("serialized filter mismatch: got %x want %x\n",
got.Bytes(), want)
continue
}
}
}
// TestFilterInsert ensures inserting data into the filter with a tweak causes
// that data to be matched and the resulting serialized MsgFilterLoad is the
// expected value.
func TestFilterInsertWithTweak(t *testing.T) {
var tests = []struct {
hex string
insert bool
}{
{"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true},
{"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false},
{"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true},
{"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true},
}
f := bloom.NewFilter(3, 2147483649, 0.01, wire.BloomUpdateAll)
for i, test := range tests {
data, err := hex.DecodeString(test.hex)
if err != nil {
t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
return
}
if test.insert {
f.Add(data)
}
result := f.Matches(data)
if test.insert != result {
t.Errorf("TestFilterInsertWithTweak Matches test #%d failure: got %v want %v\n",
i, result, test.insert)
return
}
}
want, err := hex.DecodeString("03ce4299050000000100008001")
if err != nil {
t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
return
}
got := bytes.NewBuffer(nil)
err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion)
if err != nil {
t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err)
return
}
if !bytes.Equal(got.Bytes(), want) {
t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n",
got.Bytes(), want)
return
}
}
// TestFilterInsertKey ensures inserting public keys and addresses works as
// expected.
func TestFilterInsertKey(t *testing.T) {
secret := "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"
wif, err := btcutil.DecodeWIF(secret)
if err != nil {
t.Errorf("TestFilterInsertKey DecodeWIF failed: %v", err)
return
}
f := bloom.NewFilter(2, 0, 0.001, wire.BloomUpdateAll)
f.Add(wif.SerializePubKey())
f.Add(btcutil.Hash160(wif.SerializePubKey()))
want, err := hex.DecodeString("038fc16b080000000000000001")
if err != nil {
t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err)
return
}
got := bytes.NewBuffer(nil)
err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion)
if err != nil {
t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err)
return
}
if !bytes.Equal(got.Bytes(), want) {
t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n",
got.Bytes(), want)
return
}
}
func TestFilterBloomMatch(t *testing.T) {
str := "01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e" +
"88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7" +
"c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d2" +
"7d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee" +
"51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5e" +
"eef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c33" +
"9ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3" +
"bc6e2754dbcff1988ac2f15de00000000001976a914a266436d296554760" +
"8b9e15d9032a7b9d64fa43188ac00000000"
strBytes, err := hex.DecodeString(str)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failure: %v", err)
return
}
tx, err := btcutil.NewTxFromBytes(strBytes)
if err != nil {
t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err)
return
}
spendingTxBytes := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f,
0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6,
0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27,
0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f,
0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30,
0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce,
0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57,
0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0,
0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c,
0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00,
0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e,
0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27,
0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01,
0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10,
0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9,
0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5,
0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff,
0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf,
0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9,
0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb,
0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b,
0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76,
0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07,
0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0,
0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8,
0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14,
0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51,
0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70,
0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00}
spendingTx, err := btcutil.NewTxFromBytes(spendingTxBytes)
if err != nil {
t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err)
return
}
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr := "b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"
hash, err := chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
return
}
f.AddHash(hash)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"
hashBytes, err := hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065" +
"f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643" +
"ac4cb7cb3c462aced7f14711a01"
hashBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match input signature %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95" +
"c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe" +
"76036c339"
hashBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match input pubkey %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "04943fdd508053c75000106d3bc6e2754dbcff19"
hashBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr)
}
if !f.MatchTxAndUpdate(spendingTx) {
t.Errorf("TestFilterBloomMatch spendingTx didn't match output address %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "a266436d2965547608b9e15d9032a7b9d64fa431"
hashBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
return
}
outpoint := wire.NewOutPoint(hash, 0)
f.AddOutPoint(outpoint)
if !f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch didn't match outpoint %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
return
}
f.AddHash(hash)
if f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch matched hash %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "0000006d2965547608b9e15d9032a7b9d64fa431"
hashBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err)
return
}
f.Add(hashBytes)
if f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch matched address %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
return
}
outpoint = wire.NewOutPoint(hash, 1)
f.AddOutPoint(outpoint)
if f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr)
}
f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
inputStr = "000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err)
return
}
outpoint = wire.NewOutPoint(hash, 0)
f.AddOutPoint(outpoint)
if f.MatchTxAndUpdate(tx) {
t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr)
}
}
func TestFilterInsertUpdateNone(t *testing.T) {
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateNone)
// Add the generation pubkey
inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" +
"876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" +
"2252247d97a46a91"
inputBytes, err := hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err)
return
}
f.Add(inputBytes)
// Add the output address for the 4th transaction
inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21"
inputBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err)
return
}
f.Add(inputBytes)
inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"
hash, err := chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err)
return
}
outpoint := wire.NewOutPoint(hash, 0)
if f.MatchesOutPoint(outpoint) {
t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr)
return
}
inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err)
return
}
outpoint = wire.NewOutPoint(hash, 0)
if f.MatchesOutPoint(outpoint) {
t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr)
return
}
}
func TestFilterInsertP2PubKeyOnly(t *testing.T) {
blockStr := "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc" +
"880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367" +
"117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010" +
"00000000000000000000000000000000000000000000000000000000000" +
"0000ffffffff07044c86041b0136ffffffff0100f2052a0100000043410" +
"4eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2" +
"c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a22522" +
"47d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255" +
"120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356" +
"e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062e" +
"a10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa" +
"608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ec" +
"bba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141" +
"b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac0000000001000000" +
"03fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26a" +
"f16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23" +
"b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6" +
"b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e" +
"29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245b" +
"d69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585" +
"caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e7" +
"5429df397b5af83000000004948304502202bdb79c596a9ffc24e96f438" +
"6199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b72" +
"4fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffff" +
"ff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cb" +
"cb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9cecc" +
"d328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f11" +
"87779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff010071" +
"4460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8" +
"d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397" +
"cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3" +
"e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e4022100" +
"8581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7" +
"c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf64852" +
"61c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d" +
"3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f2" +
"48e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124" +
"c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93" +
"0220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346" +
"669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6" +
"485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270e" +
"fb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051" +
"fd372bb7a537232946e0a46f53636b4dafdaa4000000008c49304602210" +
"0c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de" +
"35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46f" +
"c37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0" +
"f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f" +
"4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f8" +
"94aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493" +
"046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8a" +
"a788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415" +
"588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb" +
"7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018" +
"ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8" +
"040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188a" +
"c000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" +
"f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34" +
"fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243" +
"bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec" +
"20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442" +
"e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632" +
"d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10" +
"eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a91" +
"4a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000" +
"000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850" +
"927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec" +
"2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a25" +
"7b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e5" +
"21fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455f" +
"e30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098" +
"544bffffffff0240420f00000000001976a9144676d1b820d63ec272f19" +
"00d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00" +
"d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc91750" +
"1ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f10000" +
"00008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e" +
"280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba80" +
"7892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b" +
"5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c4" +
"7d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41e" +
"d70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d0" +
"68000000008b4830450221008513ad65187b903aed1102d1d0c47688127" +
"658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de6603" +
"5fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50b" +
"e1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b0682" +
"0edca9ef982c35fda2d255afba340068c5035552368bc7200c1488fffff" +
"fff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e40" +
"0f8699eb4888ac00000000"
blockBytes, err := hex.DecodeString(blockStr)
if err != nil {
t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
return
}
block, err := btcutil.NewBlockFromBytes(blockBytes)
if err != nil {
t.Errorf("TestFilterInsertP2PubKeyOnly NewBlockFromBytes failed: %v", err)
return
}
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateP2PubkeyOnly)
// Generation pubkey
inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" +
"876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" +
"2252247d97a46a91"
inputBytes, err := hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
return
}
f.Add(inputBytes)
// Output address of 4th transaction
inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21"
inputBytes, err = hex.DecodeString(inputStr)
if err != nil {
t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
return
}
f.Add(inputBytes)
// Ignore return value -- this is just used to update the filter.
_, _ = bloom.NewMerkleBlock(block, f)
// We should match the generation pubkey
inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"
hash, err := chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err)
return
}
outpoint := wire.NewOutPoint(hash, 0)
if !f.MatchesOutPoint(outpoint) {
t.Errorf("TestMerkleBlockP2PubKeyOnly didn't match the generation "+
"outpoint %s", inputStr)
return
}
// We should not match the 4th transaction, which is not p2pk
inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"
hash, err = chainhash.NewHashFromStr(inputStr)
if err != nil {
t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err)
return
}
outpoint = wire.NewOutPoint(hash, 0)
if f.MatchesOutPoint(outpoint) {
t.Errorf("TestMerkleBlockP2PubKeyOnly matched outpoint %s", inputStr)
return
}
}
func TestFilterReload(t *testing.T) {
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
bFilter := bloom.LoadFilter(f.MsgFilterLoad())
if bFilter.MsgFilterLoad() == nil {
t.Errorf("TestFilterReload LoadFilter test failed")
return
}
bFilter.Reload(nil)
if bFilter.MsgFilterLoad() != nil {
t.Errorf("TestFilterReload Reload test failed")
}
}