Fix payment notification backup import/export.

This commit is contained in:
Greyson Parrelli
2024-09-22 15:09:04 -04:00
parent a76f5e600e
commit ecd16dbe9c
3 changed files with 46 additions and 17 deletions

View File

@@ -503,7 +503,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
PaymentNotification( PaymentNotification(
amountMob = payment.amount.serializeAmountString(), amountMob = payment.amount.serializeAmountString(),
feeMob = payment.fee.serializeAmountString(), feeMob = payment.fee.serializeAmountString(),
note = payment.note, note = payment.note.takeUnless { it.isEmpty() },
transactionDetails = payment.getTransactionDetails() transactionDetails = payment.getTransactionDetails()
) )
} }
@@ -789,16 +789,18 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
} }
private fun PaymentTable.PaymentTransaction.getTransactionDetails(): PaymentNotification.TransactionDetails? { private fun PaymentTable.PaymentTransaction.getTransactionDetails(): PaymentNotification.TransactionDetails? {
if (failureReason != null || state == State.FAILED) { if (this.failureReason != null || this.state == State.FAILED) {
return PaymentNotification.TransactionDetails(failedTransaction = PaymentNotification.TransactionDetails.FailedTransaction(reason = failureReason.toBackupFailureReason())) return PaymentNotification.TransactionDetails(failedTransaction = PaymentNotification.TransactionDetails.FailedTransaction(reason = this.failureReason.toBackupFailureReason()))
} }
return PaymentNotification.TransactionDetails( return PaymentNotification.TransactionDetails(
transaction = PaymentNotification.TransactionDetails.Transaction( transaction = PaymentNotification.TransactionDetails.Transaction(
status = this.state.toBackupState(), status = this.state.toBackupState(),
timestamp = timestamp, timestamp = this.timestamp,
blockIndex = blockIndex, blockIndex = this.blockIndex,
blockTimestamp = blockTimestamp, blockTimestamp = this.blockTimestamp,
mobileCoinIdentification = paymentMetaData.mobileCoinTxoIdentification?.toBackup() mobileCoinIdentification = this.paymentMetaData.mobileCoinTxoIdentification?.toBackup(),
transaction = this.transaction?.toByteString(),
receipt = this.receipt?.toByteString()
) )
) )
} }

View File

@@ -62,6 +62,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent
import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.mms.QuoteModel
import org.thoughtcrime.securesms.payments.CryptoValueUtil import org.thoughtcrime.securesms.payments.CryptoValueUtil
import org.thoughtcrime.securesms.payments.Direction import org.thoughtcrime.securesms.payments.Direction
import org.thoughtcrime.securesms.payments.FailureReason
import org.thoughtcrime.securesms.payments.State import org.thoughtcrime.securesms.payments.State
import org.thoughtcrime.securesms.payments.proto.PaymentMetaData import org.thoughtcrime.securesms.payments.proto.PaymentMetaData
import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.profiles.ProfileName
@@ -494,6 +495,7 @@ class ChatItemImportInserter(
chatRecipientId, chatRecipientId,
transaction.timestamp ?: 0, transaction.timestamp ?: 0,
transaction.blockIndex ?: 0, transaction.blockIndex ?: 0,
transaction.blockTimestamp ?: 0,
paymentNotification.note ?: "", paymentNotification.note ?: "",
if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED, if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED,
transaction.status.toLocalStatus(), transaction.status.toLocalStatus(),
@@ -502,7 +504,8 @@ class ChatItemImportInserter(
transaction.transaction?.toByteArray(), transaction.transaction?.toByteArray(),
transaction.receipt?.toByteArray(), transaction.receipt?.toByteArray(),
mobileCoinIdentification, mobileCoinIdentification,
chatItem.incoming?.read ?: true chatItem.incoming?.read ?: true,
null
) )
} }
@@ -710,17 +713,17 @@ class ChatItemImportInserter(
private fun ContentValues.addPaymentNotification(chatItem: ChatItem, chatRecipientId: RecipientId) { private fun ContentValues.addPaymentNotification(chatItem: ChatItem, chatRecipientId: RecipientId) {
val paymentNotification = chatItem.paymentNotification!! val paymentNotification = chatItem.paymentNotification!!
if (chatItem.paymentNotification.amountMob.isNullOrEmpty()) { if (chatItem.paymentNotification.amountMob.isNullOrEmpty()) {
addPaymentTombstoneNoAmount() this.addPaymentTombstoneNoAmount()
return return
} }
val amount = paymentNotification.amountMob?.tryParseMoney() ?: return addPaymentTombstoneNoAmount() val amount = paymentNotification.amountMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount()
val fee = paymentNotification.feeMob?.tryParseMoney() ?: return addPaymentTombstoneNoAmount() val fee = paymentNotification.feeMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount()
if (chatItem.paymentNotification.transactionDetails?.failedTransaction != null) { if (chatItem.paymentNotification.transactionDetails?.failedTransaction != null) {
addFailedPaymentNotification(chatItem, amount, fee, chatRecipientId) this.addFailedPaymentNotification(chatItem, amount, fee, chatRecipientId)
return return
} }
addPaymentTombstoneNoMetadata(chatItem.paymentNotification) this.addPaymentTombstoneNoMetadata(chatItem.paymentNotification)
} }
private fun PaymentNotification.TransactionDetails.MobileCoinTxoIdentification.toLocal(): PaymentMetaData { private fun PaymentNotification.TransactionDetails.MobileCoinTxoIdentification.toLocal(): PaymentMetaData {
@@ -737,6 +740,7 @@ class ChatItemImportInserter(
chatRecipientId, chatRecipientId,
0, 0,
0, 0,
0,
chatItem.paymentNotification?.note ?: "", chatItem.paymentNotification?.note ?: "",
if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED, if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED,
State.FAILED, State.FAILED,
@@ -745,7 +749,8 @@ class ChatItemImportInserter(
null, null,
null, null,
null, null,
chatItem.incoming?.read ?: true chatItem.incoming?.read ?: true,
chatItem.paymentNotification?.transactionDetails?.failedTransaction?.reason?.toLocalPaymentFailureReason()
) )
if (uuid != null) { if (uuid != null) {
put(MessageTable.BODY, uuid.toString()) put(MessageTable.BODY, uuid.toString())
@@ -755,6 +760,14 @@ class ChatItemImportInserter(
} }
} }
private fun PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.toLocalPaymentFailureReason(): FailureReason {
return when (this) {
PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.GENERIC -> FailureReason.UNKNOWN
PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.NETWORK -> FailureReason.NETWORK
PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.INSUFFICIENT_FUNDS -> FailureReason.INSUFFICIENT_FUNDS
}
}
private fun ContentValues.addPaymentTombstoneNoAmount() { private fun ContentValues.addPaymentTombstoneNoAmount() {
put(MessageTable.TYPE, getAsLong(MessageTable.TYPE) or MessageTypes.SPECIAL_TYPE_PAYMENTS_TOMBSTONE) put(MessageTable.TYPE, getAsLong(MessageTable.TYPE) or MessageTypes.SPECIAL_TYPE_PAYMENTS_TOMBSTONE)
} }

View File

@@ -186,6 +186,7 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData
public UUID restoreFromBackup(@NonNull RecipientId recipientId, public UUID restoreFromBackup(@NonNull RecipientId recipientId,
long timestamp, long timestamp,
long blockIndex, long blockIndex,
long blockTimestamp,
@NonNull String note, @NonNull String note,
@NonNull Direction direction, @NonNull Direction direction,
@NonNull State state, @NonNull State state,
@@ -194,10 +195,16 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData
@Nullable byte[] transaction, @Nullable byte[] transaction,
@Nullable byte[] receipt, @Nullable byte[] receipt,
@Nullable PaymentMetaData metaData, @Nullable PaymentMetaData metaData,
boolean seen) { boolean seen,
@Nullable FailureReason failureReason)
{
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
try { try {
create(uuid, recipientId, null, timestamp, blockIndex, note, direction, state, amount, fee, transaction, receipt, metaData, seen); create(uuid, recipientId, null, timestamp, blockIndex, note, direction, state, amount, fee, transaction, receipt, metaData, seen);
updateBlockDetails(uuid, blockIndex, blockTimestamp);
if (failureReason != null) {
markPaymentFailed(uuid, failureReason);
}
} catch (SerializationException | PublicKeyConflictException e) { } catch (SerializationException | PublicKeyConflictException e) {
return null; return null;
} }
@@ -619,13 +626,20 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData
} }
private static @NonNull PaymentTransaction readPayment(@NonNull Cursor cursor) { private static @NonNull PaymentTransaction readPayment(@NonNull Cursor cursor) {
State state = State.deserialize(CursorUtil.requireInt(cursor, STATE));
FailureReason failureReason = null;
if (state == State.FAILED) {
failureReason = FailureReason.deserialize(CursorUtil.requireInt(cursor, FAILURE));
}
return new PaymentTransaction(UUID.fromString(CursorUtil.requireString(cursor, PAYMENT_UUID)), return new PaymentTransaction(UUID.fromString(CursorUtil.requireString(cursor, PAYMENT_UUID)),
getRecipientId(cursor), getRecipientId(cursor),
MobileCoinPublicAddress.fromBase58NullableOrThrow(CursorUtil.requireString(cursor, ADDRESS)), MobileCoinPublicAddress.fromBase58NullableOrThrow(CursorUtil.requireString(cursor, ADDRESS)),
CursorUtil.requireLong(cursor, TIMESTAMP), CursorUtil.requireLong(cursor, TIMESTAMP),
Direction.deserialize(CursorUtil.requireInt(cursor, DIRECTION)), Direction.deserialize(CursorUtil.requireInt(cursor, DIRECTION)),
State.deserialize(CursorUtil.requireInt(cursor, STATE)), state,
FailureReason.deserialize(CursorUtil.requireInt(cursor, FAILURE)), failureReason,
CursorUtil.requireString(cursor, NOTE), CursorUtil.requireString(cursor, NOTE),
getMoneyValue(CursorUtil.requireBlob(cursor, AMOUNT)), getMoneyValue(CursorUtil.requireBlob(cursor, AMOUNT)),
getMoneyValue(CursorUtil.requireBlob(cursor, FEE)), getMoneyValue(CursorUtil.requireBlob(cursor, FEE)),