Skip to content

Commit

Permalink
Merge pull request #1810 from ardriveapp/PE-6517-implement-pre-sync-v…
Browse files Browse the repository at this point in the history
…erification-of-snapshot-existence

PE-6517: feat(snapshots)
  • Loading branch information
thiagocarvalhodev authored Jul 30, 2024
2 parents 5458969 + 4becb08 commit 0ab4893
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 1 deletion.
4 changes: 4 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'package:ardrive/services/authentication/biometric_authentication.dart';
import 'package:ardrive/services/config/config_fetcher.dart';
import 'package:ardrive/shared/blocs/banner/app_banner_bloc.dart';
import 'package:ardrive/sharing/blocs/sharing_file_bloc.dart';
import 'package:ardrive/sync/data/snapshot_validation_service.dart';
import 'package:ardrive/sync/domain/repositories/sync_repository.dart';
import 'package:ardrive/sync/utils/batch_processor.dart';
import 'package:ardrive/theme/theme_switcher_bloc.dart';
Expand Down Expand Up @@ -423,6 +424,9 @@ class AppState extends State<App> {
driveDao: _.read<DriveDao>(),
licenseService: _.read<LicenseService>(),
batchProcessor: BatchProcessor(),
snapshotValidationService: SnapshotValidationService(
configService: configService,
),
),
),
RepositoryProvider(
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/drive_detail/drive_detail_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class _DriveDetailPageState extends State<DriveDetailPage> {
},
child: BlocBuilder<DriveDetailCubit, DriveDetailState>(
buildWhen: (previous, current) {
return context.read<SyncCubit>().state is! SyncInProgress;
return widget.context.read<SyncCubit>().state is! SyncInProgress;
},
builder: (context, driveDetailState) {
if (driveDetailState is DriveDetailLoadInProgress) {
Expand Down
63 changes: 63 additions & 0 deletions lib/sync/data/snapshot_validation_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:ardrive/services/config/config_service.dart';
import 'package:ardrive/utils/logger.dart';
import 'package:ardrive/utils/snapshots/snapshot_item.dart';
import 'package:http/http.dart' as http;

class SnapshotValidationService {
final ConfigService _configService;

SnapshotValidationService({
required ConfigService configService,
}) : _configService = configService;

Future<List<SnapshotItem>> validateSnapshotItems(
List<SnapshotItem> snapshotItems,
) async {
List<SnapshotItem> snapshotsVerified = [];

final futures = snapshotItems.map((snapshotItem) async {
final appConfig = _configService.config;

try {
final snapshotValidation = await http.head(
Uri.parse(
'${appConfig.defaultArweaveGatewayUrl}/${snapshotItem.txId}'),
);

logger.d('Validating snapshot ${snapshotItem.txId}');

if (snapshotValidation.statusCode == 200) {
if (snapshotValidation.headers['content-length'] != null) {
int lenght =
int.parse(snapshotValidation.headers['content-length']!);

final headers = {
'Range': 'bytes=${lenght - 8}-$lenght',
};

final validationRequest = await http.get(
Uri.parse(
'${appConfig.defaultArweaveGatewayUrl}${snapshotItem.txId}'),
headers: headers,
);

logger.d(
'Validation request status code: ${validationRequest.statusCode}');
}
logger.d('Snapshot ${snapshotItem.txId} is valid');

snapshotsVerified.add(snapshotItem);
}
} catch (e) {
logger.w('Error while validating snapshot. ${snapshotItem.txId}');
}
});

await Future.wait(futures);

snapshotItems.clear();
snapshotItems = snapshotsVerified;

return snapshotItems;
}
}
11 changes: 11 additions & 0 deletions lib/sync/domain/repositories/sync_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'package:ardrive/services/config/config.dart';
import 'package:ardrive/services/license/license_service.dart';
import 'package:ardrive/services/license/license_state.dart';
import 'package:ardrive/sync/constants.dart';
import 'package:ardrive/sync/data/snapshot_validation_service.dart';
import 'package:ardrive/sync/domain/ghost_folder.dart';
import 'package:ardrive/sync/domain/models/drive_entity_history.dart';
import 'package:ardrive/sync/domain/sync_progress.dart';
Expand Down Expand Up @@ -89,13 +90,15 @@ abstract class SyncRepository {
required ConfigService configService,
required LicenseService licenseService,
required BatchProcessor batchProcessor,
required SnapshotValidationService snapshotValidationService,
}) {
return _SyncRepository(
arweave: arweave,
driveDao: driveDao,
configService: configService,
licenseService: licenseService,
batchProcessor: batchProcessor,
snapshotValidationService: snapshotValidationService,
);
}
}
Expand All @@ -106,6 +109,7 @@ class _SyncRepository implements SyncRepository {
final ConfigService _configService;
final LicenseService _licenseService;
final BatchProcessor _batchProcessor;
final SnapshotValidationService _snapshotValidationService;

final Map<String, GhostFolder> _ghostFolders = {};
final Set<String> _folderIds = <String>{};
Expand All @@ -118,10 +122,12 @@ class _SyncRepository implements SyncRepository {
required ConfigService configService,
required LicenseService licenseService,
required BatchProcessor batchProcessor,
required SnapshotValidationService snapshotValidationService,
}) : _arweave = arweave,
_driveDao = driveDao,
_configService = configService,
_licenseService = licenseService,
_snapshotValidationService = snapshotValidationService,
_batchProcessor = batchProcessor;

@override
Expand Down Expand Up @@ -552,6 +558,11 @@ class _SyncRepository implements SyncRepository {
snapshotsStream,
arweave: _arweave,
).toList();

List<SnapshotItem> snapshotsVerified =
await _snapshotValidationService.validateSnapshotItems(snapshotItems);

snapshotItems = snapshotsVerified;
}

final SnapshotDriveHistory snapshotDriveHistory = SnapshotDriveHistory(
Expand Down
4 changes: 4 additions & 0 deletions lib/utils/snapshots/snapshot_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ abstract class SnapshotItem implements SegmentedGQLData {
abstract final int blockStart;
abstract final int blockEnd;
abstract final DriveID driveId;
abstract final String txId;

factory SnapshotItem.fromGQLNode({
required SnapshotEntityTransaction node,
Expand Down Expand Up @@ -72,6 +73,7 @@ abstract class SnapshotItem implements SegmentedGQLData {
fakeSource: fakeSource,
arweave: arweave,
);

} catch (e) {
logger.e('Ignoring snapshot transaction with invalid block range', e);
continue;
Expand Down Expand Up @@ -133,6 +135,8 @@ abstract class SnapshotItem implements SegmentedGQLData {

class SnapshotItemOnChain implements SnapshotItem {
final int timestamp;

@override
final TxID txId;
String? _cachedSource;
int _currentIndex = -1;
Expand Down

0 comments on commit 0ab4893

Please sign in to comment.