class DetailsDataStore {

    public synchronized ContractDetails get(UscAddress addr, byte[] codeHash) {
        ContractDetails details = cache.get(addr);
        boolean isDifferentCodeHash = false;

        if (details == null) {

            if (removes.contains(addr)) {
                return null;
            }
            byte[] data = db.get(addr.getBytes());
            if (data == null) {
                return null;
            }

            details = createContractDetails(data, trieStorePool, memoryStorageLimit);
            cache.put(addr, details);

            float out = ((float) data.length) / 1048576;
            if (out > 10) {
                String sizeFmt = format("%02.2f", out);
                gLogger.debug("loaded: address: {}, size: {}MB", addr, sizeFmt);
            }
        } else {
            isDifferentCodeHash = !Arrays.equals(codeHash, details.getCodeHash());
            if (details.getCode() != null && isDifferentCodeHash) {
                byte[] oldCode = details.getCode();
                String dataSourceName = ((ContractDetailsImpl) details).getDataSourceName();
                TrieStoreImpl trieStore = (TrieStoreImpl) trieStorePool.getInstanceFor(dataSourceName);
                trieStore.storeValue(Keccak256Helper.keccak256(oldCode), oldCode);
            }
        }

        // we avoid doing twice codeHash comparison
        if (isDifferentCodeHash || !Arrays.equals(codeHash, details.getCodeHash())) {
            ((ContractDetailsImpl) details).fixCodeBy(codeHash);
        }

        return details;
    }

    public  DetailsDataStore(DatabaseImpl db, TrieStore.Pool trieStorePool, int memoryStorageLimit);

}