loadXchain method Null safety

Future<Map<BlockModel, List<TransactionModel>>> loadXchain(
  1. XchainModel xchain,
  2. {List<String> skip = const []}
)

Deserializes and persists all the blocks from the xchain into database.

Implementation

Future<Map<BlockModel, List<TransactionModel>>> loadXchain(XchainModel xchain,
    {List<String> skip = const []}) async {
  Map<String, Uint8List> serializedblocks =
      await _l0storage.getAll(base64Url.encode(xchain.address));
  Map<BlockModel, List<TransactionModel>> blocks = {};
  for (String blockId in serializedblocks.keys) {
    if (blockId == 'public.key' ||
        skip.contains(blockId.replaceAll('.block', ''))) continue;
    Uint8List serializedBackup = serializedblocks[blockId]!;
    List<Uint8List> backupList = CompactSize.decode(serializedBackup);
    Uint8List signature = backupList[0];
    Uint8List serializedBlock = backupList[1];
    if (!Rsa.verify(xchain.publicKey, serializedBlock, signature)) {
      throw StateError('Backup signature could not be verified for $blockId');
    }
    BlockModel block = BlockModel.deserialize(serializedBlock);
    if (!Bytes.memEquals(Digest('SHA3-256').process(block.serialize()),
        base64Url.decode(blockId.replaceAll('.block', '')))) {
      throw Exception('Corrupted Block ${block.toString()}');
    }
    List<TransactionModel> transactions =
        TransactionService.deserializeTransactions(serializedBlock);
    MerkelTree merkelTree = MerkelTree.build(
        transactions.map((TransactionModel txn) => txn.id!).toList());
    if (!Bytes.memEquals(block.transactionRoot, merkelTree.root!)) {
      throw Exception('Invalid transaction root for ${block.toString()}');
    }
    for (TransactionModel transaction in transactions) {
      transaction.block = block;
      transaction.merkelProof = merkelTree.proofs[transaction.id!];
      if (!TransactionService.validateAuthor(transaction, xchain.publicKey)) {
        throw Exception(
            'Transaction authorshhip could not be verified: ${transaction.toString()}');
      }
    }
    block.transactionRoot = merkelTree.root!;
    blocks[block] = transactions;
  }
  return blocks;
}