예제 #1
0
        public void RealScriptPubKeyFilterTest()
        {
            var scripts = new List <Script>();

            for (var i = 0; i < 10_000; i++)
            {
                var script = new Key().PubKey.GetSegwitAddress(Network.Main).ScriptPubKey;
                scripts.Add(script);
            }

            var key     = Hashes.Hash256(Encoding.ASCII.GetBytes("A key for testing"));
            var builder = new GolombRiceFilterBuilder()
                          .SetKey(key)
                          .SetP(0x20);

            foreach (var script in scripts)
            {
                builder = builder.AddScriptPubkey(script);
            }

            var filter = builder.Build();

            var keyMatch = key.ToBytes().SafeSubarray(0, 16);

            foreach (var script in scripts)
            {
                var match = filter.MatchAny(new[] { script.ToBytes() }, keyMatch);
                Assert.True(match);
            }
        }
예제 #2
0
        public void Setup()
        {
            var keyBuffer = new byte[32];

            _random.NextBytes(keyBuffer);
            var key = new uint256(keyBuffer);

            _testKey = key.ToBytes().Take(16).ToArray();

            var builder = new GolombRiceFilterBuilder()
                          .SetKey(key)
                          .SetP(20);

            var itemsInFilter = new List <byte[]>();

            for (var j = 0; j < N; j++)
            {
                var data = new byte[_random.Next(20, 30)];
                _random.NextBytes(data);
                itemsInFilter.Add(data);
            }
            builder.AddEntries(itemsInFilter);
            _sample = itemsInFilter.OrderBy(x => _random.Next()).Take(N / 200).ToArray();
            _filter = builder.Build();
        }
예제 #3
0
        private FilterModel CreateFiltersWith(IEnumerable <byte[]> scripts)
        {
            var keyBuffer = new byte[32];

            Random.NextBytes(keyBuffer);
            var blockHash = new uint256(keyBuffer);

            var builder = new GolombRiceFilterBuilder()
                          .SetKey(blockHash)
                          .SetP(20);

            builder.AddEntries(scripts);
            return(new FilterModel(
                       new SmartHeader(new uint256(blockHash), uint256.One, 0, DateTimeOffset.UtcNow),
                       builder.Build()));
        }
        private FilterModel CreateFiltersWith(IEnumerable <byte[]> scripts)
        {
            var keyBuffer = new byte[32];

            Random.NextBytes(keyBuffer);
            var blockHash = new uint256(keyBuffer);

            var builder = new GolombRiceFilterBuilder()
                          .SetKey(blockHash)
                          .SetP(20);

            builder.AddEntries(scripts);
            return(new FilterModel
            {
                BlockHeight = 0,
                BlockHash = new uint256(blockHash),
                Filter = builder.Build()
            });
        }
예제 #5
0
        public void FalsePositivesTest()
        {
            // Given this library can be used for building and query filters for each block of
            // the bitcoin's blockchain, we must be sure it performs well, specially in the queries.

            // Considering a 4MB block (overestimated) with an average transaction size of 250 bytes (underestimated)
            // gives us 16000 transactions (this is about 27 tx/sec). Assuming 2.5 txouts per tx we have 83885 txouts
            // per block.
            const byte P                    = 20;
            const int  blockCount           = 100;
            const int  maxBlockSize         = 4_000_000;
            const int  avgTxSize            = 250;                  // Currently the average is around 1kb.
            const int  txoutCountPerBlock   = maxBlockSize / avgTxSize;
            const int  avgTxoutPushDataSize = 20;                   // P2PKH scripts has 20 bytes.
            const int  walletAddressCount   = 1_000;                // We estimate that our user will have 1000 addresses.

            var key     = Hashes.Hash256(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
            var testKey = key.ToBytes().SafeSubarray(0, 16);

            // Generation of data to be added into the filter
            var random = new Random();

            var blocks = new List <BlockFilter>(blockCount);

            for (var i = 0; i < blockCount; i++)
            {
                var builder = new GolombRiceFilterBuilder()
                              .SetKey(key)
                              .SetP(P);

                var txouts = new List <byte[]>(txoutCountPerBlock);
                for (var j = 0; j < txoutCountPerBlock; j++)
                {
                    var pushDataBuffer = new byte[avgTxoutPushDataSize];
                    random.NextBytes(pushDataBuffer);
                    txouts.Add(pushDataBuffer);
                }

                builder.AddEntries(txouts);

                var filter = builder.Build();

                blocks.Add(new BlockFilter(filter, txouts));
            }

            var walletAddresses    = new List <byte[]>(walletAddressCount);
            var falsePositiveCount = 0;

            for (var i = 0; i < walletAddressCount; i++)
            {
                var walletAddress = new byte[avgTxoutPushDataSize];
                random.NextBytes(walletAddress);
                walletAddresses.Add(walletAddress);
            }

            // Check that the filter can match every single txout in every block.
            foreach (var block in blocks)
            {
                if (block.Filter.MatchAny(walletAddresses, testKey))
                {
                    falsePositiveCount++;
                }
            }

            Assert.True(falsePositiveCount < 5);

            // Filter has to mat existing values
            var falseNegativeCount = 0;

            // Check that the filter can match every single txout in every block.
            foreach (var block in blocks)
            {
                if (!block.Filter.MatchAny(block.Data, testKey))
                {
                    falseNegativeCount++;
                }
            }

            Assert.Equal(0, falseNegativeCount);
        }
예제 #6
0
 public GolombRiceFilter Build() => _builder.Build();