예제 #1
0
        public StateSyncFeed(
            ISnapshotableDb codeDb,
            ISnapshotableDb stateDb,
            IDb tempDb,
            ISyncModeSelector syncModeSelector,
            IBlockTree blockTree,
            ILogManager logManager)
        {
            _codeDb                    = codeDb?.Innermost ?? throw new ArgumentNullException(nameof(codeDb));
            _stateDb                   = stateDb?.Innermost ?? throw new ArgumentNullException(nameof(stateDb));
            _tempDb                    = tempDb ?? throw new ArgumentNullException(nameof(tempDb));
            _blockTree                 = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
            _syncModeSelector          = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector));
            _syncModeSelector.Changed += SyncModeSelectorOnChanged;

            _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager));

            byte[] progress = _codeDb.Get(_fastSyncProgressKey);
            _data         = new DetailedProgress(_blockTree.ChainId, progress);
            _pendingItems = new PendingSyncItems();
            _syncProgress = new StateSyncProgress(0, _logger);
        }
예제 #2
0
        public void ResetStateRoot(long blockNumber, Keccak stateRoot)
        {
            if (CurrentState != SyncFeedState.Dormant)
            {
                throw new InvalidOperationException("Cannot reset state sync on an active feed");
            }

            Interlocked.Exchange(ref _hintsToResetRoot, 0);

            if (_logger.IsInfo)
            {
                _logger.Info($"Setting state sync state root to {blockNumber} {stateRoot}");
            }
            _currentSyncStart = DateTime.UtcNow;
            _currentSyncStartSecondsInSync = _data.SecondsInSync;

            _data.LastReportTime          = (DateTime.UtcNow, DateTime.UtcNow);
            _data.LastSavedNodesCount     = _data.SavedNodesCount;
            _data.LastRequestedNodesCount = _data.RequestedNodesCount;
            if (_rootNode != stateRoot)
            {
                _syncProgress = new StateSyncProgress(blockNumber, _logger);
                _blockNumber  = blockNumber;
                _rootNode     = stateRoot;
                lock (_dependencies) _dependencies.Clear();
                lock (_codesSameAsNodes) _codesSameAsNodes.Clear();

                _pendingItems.Clear();

                if (_logger.IsDebug)
                {
                    _logger.Debug($"Clearing node stacks ({_pendingItems.Description})");
                }
            }
            else
            {
                foreach ((StateSyncBatch pendingRequest, _) in _pendingRequests)
                {
                    // re-add the pending request
                    for (int i = 0; i < pendingRequest.RequestedNodes.Length; i++)
                    {
                        AddNodeToPending(pendingRequest.RequestedNodes[i], null, "pending request", true);
                    }
                }
            }

            _pendingRequests.Clear();

            bool hasOnlyRootNode = false;

            if (_rootNode != Keccak.EmptyTreeHash)
            {
                if (_pendingItems.Count == 1)
                {
                    // state root can only be located on state stream
                    StateSyncItem potentialRoot = _pendingItems.PeekState();
                    if (potentialRoot?.Hash == _rootNode)
                    {
                        hasOnlyRootNode = true;
                    }
                }

                if (!hasOnlyRootNode)
                {
                    AddNodeToPending(new StateSyncItem(_rootNode, NodeDataType.State, 0, 0), null, "initial");
                }
            }
        }