private async Task <SmartContractRegistration> GetSmartContractRegistrationAsync(
            SmartContractRegistrationCache smartContractRegistrationCache, Address address,
            IStateCache stateCache = null)
        {
            //Cannot find registration in fork cache and lib cache
            if (smartContractRegistrationCache == null)
            {
                //Check whether stateCache has smartContract registration
                var smartContractRegistration = await GetSmartContractRegistrationFromZeroAsync(new ChainContext
                {
                    BlockHash   = _initLibBlockHash,
                    BlockHeight = _initLibBlockHeight,
                    StateCache  = stateCache
                }, address);

                if (smartContractRegistration == null)
                {
                    throw new SmartContractFindRegistrationException("failed to find registration from zero contract");
                }
                return(smartContractRegistration);
            }

            if (smartContractRegistrationCache.SmartContractRegistration.Code.IsEmpty)
            {
                smartContractRegistrationCache.SmartContractRegistration =
                    await GetSmartContractRegistrationFromZeroAsync(new ChainContext
                {
                    BlockHash   = smartContractRegistrationCache.BlockHash,
                    BlockHeight = smartContractRegistrationCache.BlockHeight
                },
                                                                    smartContractRegistrationCache.Address);
            }

            return(smartContractRegistrationCache.SmartContractRegistration);
        }
        public void AddSmartContractRegistration(Address address, Hash codeHash, BlockIndex blockIndex)
        {
            var smartContractRegistrationCache = new SmartContractRegistrationCache
            {
                Address     = address,
                BlockHash   = blockIndex.BlockHash,
                BlockHeight = blockIndex.BlockHeight,
                SmartContractRegistration = new SmartContractRegistration
                {
                    CodeHash = codeHash
                }
            };

            //Add genesis block registration cache to lib cache directly
            if (blockIndex.BlockHeight == 1)
            {
                _addressSmartContractRegistrationMappingCache.TryAdd(address, smartContractRegistrationCache);
                return;
            }

            if (!_forkCache.TryGetValue(address, out var caches))
            {
                caches = new List <SmartContractRegistrationCache>();
                _forkCache[address] = caches;
            }

            caches.Add(smartContractRegistrationCache);
        }
        private async Task <SmartContractRegistrationCache> GetSmartContractRegistrationCacheFromLibCache(
            IChainContext chainContext, Address address)
        {
            if (_smartContractRegistrationCacheProvider.TryGetLibCache(address,
                                                                       out var smartContractRegistrationCache))
            {
                return(smartContractRegistrationCache);
            }

            if (chainContext.BlockHeight > 0 && _initLibBlockHeight == 0)
            {
                var chain = await _blockchainService.GetChainAsync();

                _initLibBlockHash   = chain.LastIrreversibleBlockHash;
                _initLibBlockHeight = chain.LastIrreversibleBlockHeight;
            }

            //Use lib chain context to set lib cache. Genesis block need to execute with state cache
            var context = new ChainContext
            {
                BlockHash   = _initLibBlockHash,
                BlockHeight = _initLibBlockHeight,
                StateCache  = chainContext.BlockHeight == 0 ? chainContext.StateCache : null
            };

            if (!_deployedContractAddressProvider.CheckContractAddress(context, address))
            {
                return(null);
            }
            SmartContractRegistration smartContractRegistration;

            if (address == _defaultContractZeroCodeProvider.ContractZeroAddress)
            {
                smartContractRegistration = _defaultContractZeroCodeProvider.DefaultContractZeroRegistration;
                if (context.BlockHeight > Constants.GenesisBlockHeight)
                {
                    var executive = await GetExecutiveAsync(smartContractRegistration);

                    smartContractRegistration =
                        await GetSmartContractRegistrationFromZeroAsync(executive, context, address);
                }
            }
            else
            {
                smartContractRegistration = await GetSmartContractRegistrationFromZeroAsync(context, address);
            }

            smartContractRegistrationCache = new SmartContractRegistrationCache
            {
                SmartContractRegistration = smartContractRegistration,
                BlockHash   = context.BlockHash,
                BlockHeight = context.BlockHeight,
                Address     = address
            };
            _smartContractRegistrationCacheProvider.SetLibCache(address, smartContractRegistrationCache);
            return(smartContractRegistrationCache);
        }
 public void SetLibCache(Address address, SmartContractRegistrationCache cache)
 {
     _libCache[address] = cache;
 }
 public bool TryGetLibCache(Address address, out SmartContractRegistrationCache cache)
 {
     return(_libCache.TryGetValue(address, out cache));
 }