private void verifyMinimumTreeM(int sizeFrom, int sizeTo, int included_percent = 2, int max_tx = 5, byte numLevels = 4)
        {
            PrefixInclusionTree pit   = new PrefixInclusionTree(44, numLevels);
            HashSet <string>    txids = new HashSet <string>();

            for (int i = 0; i < RNG.Next(sizeTo - sizeFrom) + sizeFrom; i++)
            {
                string tx = generateRandomTXID();
                txids.Add(tx);
                pit.add(tx);
            }
            Trace.WriteLine(String.Format("Generated {0} transactions...", txids.Count));
            byte[]    original_tree_hash = pit.calculateTreeHash();
            Stopwatch sw = new Stopwatch();
            // chose some transactions for which to make a minimum tree
            List <string> chosenTransactions = new List <string>();

            foreach (string tx in txids)
            {
                // 10% of transactions, or at least one
                if (chosenTransactions.Count == 0 || RNG.Next(100) < included_percent)
                {
                    chosenTransactions.Add(tx);
                }
                if (chosenTransactions.Count >= max_tx)
                {
                    break;
                }
            }
            Trace.WriteLine(String.Format("Chosen {0} transactions from the list.", chosenTransactions.Count));
            sw.Start();
            byte[] minimal_tree = pit.getMinimumTreeTXList(chosenTransactions);
            sw.Stop();
            Trace.WriteLine(String.Format("Retrieving matcher-based minimum TX tree took {0} ms and yielded {1} bytes.", sw.ElapsedMilliseconds, minimal_tree.Length));
            sw.Reset();
            Assert.IsNotNull(minimal_tree, "PIT returns null minimal tree!");

            PrefixInclusionTree pit2 = new PrefixInclusionTree();

            sw.Start();
            pit2.reconstructMinimumTree(minimal_tree);
            sw.Stop();
            Trace.WriteLine(String.Format("Reconstructing minimum TX tree took {0} ms.", sw.ElapsedMilliseconds));
            sw.Reset();

            sw.Start();
            foreach (string tx in chosenTransactions)
            {
                Assert.IsTrue(pit2.contains(tx), "Reconstructed PIT should contain the selected transactions!");
            }
            Assert.IsTrue(original_tree_hash.SequenceEqual(pit2.calculateTreeHash()), "Minimum PIT tree does not verify successfully!");
            sw.Stop();
            Trace.WriteLine(String.Format("Verifying minimum TX tree took {0} ms.", sw.ElapsedMilliseconds));
        }
Ejemplo n.º 2
0
            public static void handleGetPIT2(byte[] data, RemoteEndpoint endpoint)
            {
                MemoryStream ms = new MemoryStream(data);

                using (BinaryReader r = new BinaryReader(ms))
                {
                    ulong  block_num  = r.ReadIxiVarUInt();
                    int    filter_len = (int)r.ReadIxiVarUInt();
                    byte[] filter     = r.ReadBytes(filter_len);
                    Cuckoo cf;
                    try
                    {
                        cf = new Cuckoo(filter);
                    }
                    catch (Exception)
                    {
                        Logging.warn("The Cuckoo filter in the getPIT message was invalid or corrupted!");
                        return;
                    }
                    Block b = Node.blockChain.getBlock(block_num, true, true);
                    if (b is null)
                    {
                        return;
                    }
                    if (b.version < BlockVer.v6)
                    {
                        Logging.warn("Neighbor {0} requested PIT information for block {0}, which was below the minimal PIT version.", endpoint.fullAddress, block_num);
                        return;
                    }
                    PrefixInclusionTree pit = new PrefixInclusionTree(44, 3);
                    List <byte[]>       interesting_transactions = new List <byte[]>();
                    foreach (var tx in b.transactions)
                    {
                        if (b.version < BlockVer.v8)
                        {
                            pit.add(UTF8Encoding.UTF8.GetBytes(Transaction.txIdV8ToLegacy(tx)));
                            if (cf.Contains(tx))
                            {
                                interesting_transactions.Add(UTF8Encoding.UTF8.GetBytes(Transaction.txIdV8ToLegacy(tx)));
                            }
                        }
                        else
                        {
                            pit.add(tx);
                            if (cf.Contains(tx))
                            {
                                interesting_transactions.Add(tx);
                            }
                        }
                    }
                    // make sure we ended up with the correct PIT
                    if (!b.pitChecksum.SequenceEqual(pit.calculateTreeHash()))
                    {
                        // This is a serious error, but I am not sure how to respond to it right now.
                        Logging.error("Reconstructed PIT for block {0} does not match the checksum in block header!", block_num);
                        return;
                    }
                    byte[]       minimal_pit = pit.getMinimumTreeTXList(interesting_transactions);
                    MemoryStream mOut        = new MemoryStream(minimal_pit.Length + 12);
                    using (BinaryWriter w = new BinaryWriter(mOut, Encoding.UTF8, true))
                    {
                        w.WriteIxiVarInt(block_num);
                        w.WriteIxiVarInt(minimal_pit.Length);
                        w.Write(minimal_pit);
                    }
                    endpoint.sendData(ProtocolMessageCode.pitData2, mOut.ToArray());
                }
            }