Ejemplo n.º 1
0
        public BaselineModule(
            ITxSender txSender,
            IStateReader stateReader,
            ILogFinder logFinder,
            IBlockFinder blockFinder,
            IAbiEncoder abiEncoder,
            IFileSystem fileSystem,
            IDb baselineDb,
            IDb metadataBaselineDb,
            ILogManager logManager,
            IBlockProcessor blockProcessor,
            DisposableStack disposableStack)
        {
            _abiEncoder         = abiEncoder ?? throw new ArgumentNullException(nameof(abiEncoder));
            _fileSystem         = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
            _baselineDb         = baselineDb ?? throw new ArgumentNullException(nameof(baselineDb));
            _metadataBaselineDb = metadataBaselineDb ?? throw new ArgumentNullException(nameof(metadataBaselineDb));
            _logger             = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager));
            _txSender           = txSender ?? throw new ArgumentNullException(nameof(txSender));
            _stateReader        = stateReader ?? throw new ArgumentNullException(nameof(stateReader));
            _logFinder          = logFinder ?? throw new ArgumentNullException(nameof(logFinder));
            _blockFinder        = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder));
            _blockProcessor     = blockProcessor ?? throw new ArgumentNullException(nameof(blockProcessor));
            _baselineTreeHelper = new BaselineTreeHelper(_logFinder, baselineDb, metadataBaselineDb, _logger);
            _disposableStack    = disposableStack ?? throw new ArgumentNullException(nameof(disposableStack));

            _metadata = LoadMetadata();
            InitTrees();
        }
        public async Task Tree_tracker_insert_leaves([ValueSource(nameof(InsertLeavesTestCases))] InsertLeavesTest test)
        {
            var address = TestItem.Addresses[0];
            var result  = await InitializeTestRpc(address);

            var          testRpc            = result.TestRpc;
            BaselineTree baselineTree       = BuildATree();
            var          fromContractAdress = ContractAddress.From(address, 0);
            var          baselineTreeHelper = new BaselineTreeHelper(testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            new BaselineTreeTracker(fromContractAdress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            var contract = new MerkleTreeSHAContract(_abiEncoder, fromContractAdress);

            UInt256 nonce = 1L;

            for (int i = 0; i < test.ExpectedTreeCounts.Length; i++)
            {
                nonce = await InsertLeavesFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();

                Assert.AreEqual(test.ExpectedTreeCounts[i], baselineTree.Count);
            }
        }
        public void GetHistoricalTree_return_expected_results([ValueSource(nameof(HistoricalTreeTestCases))] GetHistoricalLeavesTest test)
        {
            var address            = TestItem.AddressA;
            var logFinder          = Substitute.For <ILogFinder>();
            var mainDb             = new MemDb();
            var metadataDataDb     = new MemDb();
            var baselineTreeHelper = new BaselineTreeHelper(logFinder, mainDb, metadataDataDb, LimboNoErrorLogger.Instance);
            var baselineTree       = new ShaBaselineTree(mainDb, metadataDataDb, address.Bytes, BaselineModule.TruncationLength, LimboNoErrorLogger.Instance);

            for (int i = 0; i < test.Blocks.Length; i++)
            {
                var block = test.Blocks[i];
                for (int j = 0; j < block.Leaves.Length; j++)
                {
                    baselineTree.Insert(block.Leaves[j]);
                }

                baselineTree.MemorizeCurrentCount(TestItem.Keccaks[block.BlockNumber], block.BlockNumber, (uint)block.Leaves.Length);
            }

            var historicalTree = baselineTreeHelper.CreateHistoricalTree(address, 1);

            Assert.AreNotEqual(historicalTree.Count, baselineTree.Count);
            Assert.AreNotEqual(historicalTree.Root, baselineTree.Root);
        }
        public void GetHistoricalLeaves_return_expected_results([ValueSource(nameof(GetHistoricalLeafTestCases))] GetHistoricalLeavesTest test)
        {
            var logFinder          = Substitute.For <ILogFinder>();
            var mainDb             = new MemDb();
            var metadaDataDb       = new MemDb();
            var baselineTreeHelper = new BaselineTreeHelper(logFinder, new MemDb(), new MemDb(), LimboNoErrorLogger.Instance);
            var baselineTree       = new ShaBaselineTree(mainDb, metadaDataDb, new byte[] { }, BaselineModule.TruncationLength, LimboNoErrorLogger.Instance);

            for (int i = 0; i < test.Blocks.Length; i++)
            {
                var block = test.Blocks[i];
                for (int j = 0; j < block.Leaves.Length; j++)
                {
                    baselineTree.Insert(block.Leaves[j]);
                }

                baselineTree.MemorizeCurrentCount(TestItem.Keccaks[block.BlockNumber], block.BlockNumber, (uint)block.Leaves.Length);
            }

            for (int i = 0; i < test.ExpectedHashes.Length; i++)
            {
                var leavesAndBlocks = test.LeavesAndBlocksQueries[i];
                var leaves          = baselineTreeHelper.GetHistoricalLeaves(baselineTree, leavesAndBlocks.LeavesIndexes, leavesAndBlocks.BlockNumber);
                for (int j = 0; j < leavesAndBlocks.LeavesIndexes.Length; j++)
                {
                    Assert.AreEqual(test.ExpectedHashes[i][j], leaves[j].Hash);
                }
            }
        }
        public async Task Tree_tracker_reorganization([ValueSource(nameof(ReorganizationTestCases))] ReorganizedInsertLeafTest test)
        {
            Address address = TestItem.Addresses[0];

            (TestRpcBlockchain TestRpc, BaselineModule BaselineModule)result = await InitializeTestRpc(address);

            TestRpcBlockchain  testRpc            = result.TestRpc;
            BaselineTree       baselineTree       = BuildATree();
            Address            contractAddress    = ContractAddress.From(address, 0L);
            BaselineTreeHelper baselineTreeHelper = new BaselineTreeHelper(testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            new BaselineTreeTracker(contractAddress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            MerkleTreeSHAContract contract = new MerkleTreeSHAContract(_abiEncoder, contractAddress);
            UInt256 nonce = 1L;

            for (int i = 0; i < test.LeavesInBlocksCounts.Length; i++)
            {
                nonce = await InsertLeafFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();

                Assert.AreEqual(test.LeavesInBlocksCounts[i], baselineTree.Count);
            }

            int initBlocksCount = 4;
            int allBlocksCount  = initBlocksCount + test.LeavesInBlocksCounts.Length;
            TestBlockProducer testRpcBlockProducer = (TestBlockProducer)testRpc.BlockProducer;

            testRpcBlockProducer.BlockParent = testRpc.BlockTree.FindHeader(allBlocksCount);

            nonce = 1L;
            nonce = await InsertLeafFromArray(test.LeavesInMiddleOfReorganization, nonce, testRpc, contract, address);

            await testRpc.AddBlock(false);

            testRpcBlockProducer.BlockParent = testRpcBlockProducer.LastProducedBlock.Header;

            await InsertLeafFromArray(test.LeavesInAfterReorganization, nonce, testRpc, contract, address);

            await testRpc.AddBlock();

            Assert.AreEqual(test.FinalLeavesCount, baselineTree.Count);
        }
Ejemplo n.º 6
0
        public async Task Tree_tracker_start_stop_tracking([ValueSource(nameof(InsertLeafTestCases))] InsertLeafTest test)
        {
            Address address = TestItem.Addresses[0];

            (TestRpcBlockchain TestRpc, BaselineModule BaselineModule)result = await InitializeTestRpc(address);

            TestRpcBlockchain  testRpc            = result.TestRpc;
            BaselineTree       baselineTree       = BuildATree();
            Address            fromContractAdress = ContractAddress.From(address, 0L);
            BaselineTreeHelper baselineTreeHelper = new BaselineTreeHelper(testRpc.LogFinder, _baselineDb, _metadataBaselineDb, LimboNoErrorLogger.Instance);

            MerkleTreeSHAContract contract = new MerkleTreeSHAContract(_abiEncoder, fromContractAdress);
            UInt256 nonce = 1L;

            for (int i = 0; i < test.ExpectedTreeCounts.Length; i++)
            {
                nonce = await InsertLeafFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();
            }

            BaselineTreeTracker tracker = new BaselineTreeTracker(fromContractAdress, baselineTree, testRpc.BlockProcessor, baselineTreeHelper, testRpc.BlockFinder, LimboNoErrorLogger.Instance);

            Assert.AreEqual(test.ExpectedTreeCounts[test.ExpectedTreeCounts.Length - 1], baselineTree.Count);
            uint afterStartTrackingCount = baselineTree.Count;

            for (int i = 0; i < test.ExpectedTreeCounts.Length; i++)
            {
                tracker.StopTracking();
                nonce = await InsertLeafFromArray(test.LeavesInTransactionsAndBlocks[i], nonce, testRpc, contract, address);

                await testRpc.AddBlock();

                tracker.StartTracking();
                Assert.AreEqual(test.ExpectedTreeCounts[i] + afterStartTrackingCount, baselineTree.Count);
            }
        }
Ejemplo n.º 7
0
        // TODO: fuzzer with concurrent inserts
        public void Baseline_tree_fuzzer(
            int leavesPerBlock,
            int blocksCount,
            int emptyBlocksRatio,
            bool recalculateOnInsert,
            bool withReorgs,
            int?randomSeed)
        {
            MemDb              mainDb     = new MemDb();
            MemDb              metadataDb = new MemDb();
            Address            address    = Address.Zero;
            BaselineTreeHelper helper     = new BaselineTreeHelper(
                Substitute.For <ILogFinder>(), mainDb, metadataDb, LimboNoErrorLogger.Instance);
            BaselineTree baselineTree = new ShaBaselineTree(
                mainDb, metadataDb, address.Bytes, 0, LimboNoErrorLogger.Instance);

            randomSeed ??= _random.Next();
            Console.WriteLine($"random seed was {randomSeed} - hardcode it to recreate the failign test");
            // Random random = new Random(1524199427); <- example
            Random                  random                   = new Random(randomSeed.Value);
            int                     currentBlockNumber       = 0;
            uint                    totalCountCheck          = 0;
            Stack <long>            lastBlockWithLeavesCheck = new Stack <long>();
            Dictionary <long, uint> historicalCountChecks    = new Dictionary <long, uint>();

            historicalCountChecks[0] = 0;
            for (int i = 0; i < blocksCount; i++)
            {
                if (i == 18)
                {
                }
                currentBlockNumber++;
                uint numberOfLeaves = (uint)random.Next(leavesPerBlock) + 1;  // not zero
                bool hasLeaves      = random.Next(100) < emptyBlocksRatio;

                if (hasLeaves)
                {
                    totalCountCheck += numberOfLeaves;

                    TestContext.WriteLine($"Adding {numberOfLeaves} at block {currentBlockNumber}");
                    for (int j = 0; j < numberOfLeaves; j++)
                    {
                        byte[] leafBytes = new byte[32];
                        random.NextBytes(leafBytes);
                        baselineTree.Insert(new Keccak(leafBytes), recalculateOnInsert);
                    }

                    lastBlockWithLeavesCheck.TryPeek(out long previous);
                    TestContext.WriteLine($"Previous is {previous}");
                    baselineTree.LastBlockWithLeaves.Should().Be(previous);
                    baselineTree.MemorizeCurrentCount(TestItem.Keccaks[currentBlockNumber], currentBlockNumber, baselineTree.Count);
                    lastBlockWithLeavesCheck.Push(currentBlockNumber);

                    baselineTree.Count.Should().Be(totalCountCheck);
                    baselineTree.LastBlockWithLeaves.Should().Be(lastBlockWithLeavesCheck.Peek());
                }
                else
                {
                    TestContext.WriteLine($"Block {currentBlockNumber} has no leaves");
                }

                historicalCountChecks[currentBlockNumber] = totalCountCheck;

                WriteHistory(historicalCountChecks, baselineTree);

                for (int j = 1; j <= currentBlockNumber; j++)
                {
                    TestContext.WriteLine($"Creating historical at {j}");
                    var historicalTrie = helper.CreateHistoricalTree(address, j);
                    TestContext.WriteLine($"Checking if trie count ({historicalTrie.Count}) is {historicalCountChecks[j]} as expected");
                    historicalTrie.Count.Should().Be(historicalCountChecks[j], $"Block is {currentBlockNumber}, checking count at block {j}.");
                }

                if (withReorgs)
                {
                    bool shouldReorg = random.Next(100) < 50;
                    if (shouldReorg && currentBlockNumber >= 1)
                    {
                        int reorgDepth = random.Next(currentBlockNumber) + 1;
                        TestContext.WriteLine($"Reorganizing {reorgDepth} from {currentBlockNumber}");
                        uint expectedDeleteCount = historicalCountChecks[currentBlockNumber] - historicalCountChecks[currentBlockNumber - reorgDepth];
                        baselineTree.GoBackTo(currentBlockNumber - reorgDepth).Should().Be(expectedDeleteCount);
                        for (int j = 0; j < reorgDepth; j++)
                        {
                            historicalCountChecks.Remove(currentBlockNumber - j);
                        }

                        currentBlockNumber -= reorgDepth;
                        totalCountCheck     = historicalCountChecks[currentBlockNumber];
                        baselineTree.MemorizeCurrentCount(TestItem.Keccaks[currentBlockNumber], currentBlockNumber, totalCountCheck);

                        TestContext.WriteLine($"Total count after reorg is {totalCountCheck} at block {currentBlockNumber}");


                        while (lastBlockWithLeavesCheck.Any() && lastBlockWithLeavesCheck.Peek() > currentBlockNumber)
                        {
                            lastBlockWithLeavesCheck.Pop();
                        }

                        lastBlockWithLeavesCheck.TryPeek(out long last);
                        if (last != currentBlockNumber)
                        {
                            TestContext.WriteLine($"Pushing {currentBlockNumber} on test stack after reorg.");
                            // after reorg we always push a memorized count
                            lastBlockWithLeavesCheck.Push(currentBlockNumber);
                        }
                    }

                    WriteHistory(historicalCountChecks, baselineTree);
                }
            }
        }