diff --git a/wallet/res/values/strings-extra.xml b/wallet/res/values/strings-extra.xml index 293c52a8e4..0c5db8aaa3 100644 --- a/wallet/res/values/strings-extra.xml +++ b/wallet/res/values/strings-extra.xml @@ -697,4 +697,6 @@ Not used Revoked Private / Public Keys (base64) + ahead + behind \ No newline at end of file diff --git a/wallet/res/values/strings.xml b/wallet/res/values/strings.xml index 498deeaff5..cfd019d887 100644 --- a/wallet/res/values/strings.xml +++ b/wallet/res/values/strings.xml @@ -43,7 +43,7 @@ Manage apps Check date & time settings Your device time is off by %d minutes. You probably cannot send or receive Dash due to this problem.\n\nYou should check and if necessary correct your date, time and timezone settings. - Your device time is off by %d seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” to use CoinJoin. + Your device time is %s by %d seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” to use CoinJoin. Your device time is off by more than 2 seconds. You cannot use CoinJoin due to this problem.\n\nThe time settings on your device needs to be changed to “Set time automatically” before using CoinJoin. Send Dash Fetching signature from %s… diff --git a/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt b/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt index 9f14917ed8..74a9c9ac3d 100644 --- a/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt +++ b/wallet/src/de/schildbach/wallet/service/CoinJoinService.kt @@ -116,10 +116,19 @@ class CoinJoinMixingService @Inject constructor( const val DEFAULT_SESSIONS = 4 const val DEFAULT_DENOMINATIONS_GOAL = 50 const val DEFAULT_DENOMINATIONS_HARDCAP = 300 - const val MAX_ALLOWED_TIMESKEW = 4000L // 4 seconds + const val MAX_ALLOWED_AHEAD_TIMESKEW = 5000L // 5 seconds + const val MAX_ALLOWED_BEHIND_TIMESKEW = 20000L // 20 seconds // these are not for production - val FAST_MIXING_DENOMINATIONS_REMOVE = listOf() // Denomination.THOUSANDTH) + val FAST_MIXING_DENOMINATIONS_REMOVE = listOf() // Denomination.THOUSANDTH + + fun isInsideTimeSkewBounds(timeSkew: Long): Boolean { + return if (timeSkew > 0) { + timeSkew < MAX_ALLOWED_AHEAD_TIMESKEW + } else { + (-timeSkew) < MAX_ALLOWED_BEHIND_TIMESKEW + } + } } private val coinJoinManager: CoinJoinManager? @@ -148,7 +157,7 @@ class CoinJoinMixingService @Inject constructor( private var networkStatus: NetworkStatus = NetworkStatus.UNKNOWN private var isSynced = false private var hasAnonymizableBalance: Boolean = false - private var timeSkew: Long = Long.MIN_VALUE + private var timeSkew: Long = 0L // https://stackoverflow.com/questions/55421710/how-to-suspend-kotlin-coroutine-until-notified private val updateMutex = Mutex(locked = false) @@ -292,7 +301,7 @@ class CoinJoinMixingService @Inject constructor( this.mode = mode this.timeSkew = timeSkew - if (mode == CoinJoinMode.NONE || timeSkew > MAX_ALLOWED_TIMESKEW) { + if (mode == CoinJoinMode.NONE || !isInsideTimeSkewBounds(timeSkew)) { updateMixingState(MixingStatus.NOT_STARTED) } else { configureMixing() diff --git a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt index 73f72bdf9d..5ab0279b2b 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt @@ -97,17 +97,15 @@ import org.dash.wallet.common.services.analytics.AnalyticsTimer import org.dash.wallet.common.transactions.TransactionUtils.isEntirelySelf import org.dash.wallet.common.transactions.TransactionWrapper import org.dash.wallet.common.transactions.TransactionWrapperComparator -import org.dash.wallet.common.util.Constants.HTTP_CLIENT -import org.dash.wallet.common.util.head import org.dash.wallet.common.util.toBigDecimal import org.dash.wallet.integrations.crowdnode.transactions.FullCrowdNodeSignUpTxSet import org.slf4j.LoggerFactory +import java.lang.Math.abs import java.text.DecimalFormat import java.util.Currency import java.util.Locale import javax.inject.Inject import kotlin.collections.set -import kotlin.math.abs @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class) @HiltViewModel @@ -138,7 +136,9 @@ class MainViewModel @Inject constructor( private const val THROTTLE_DURATION = 500L private const val DIRECTION_KEY = "tx_direction" private const val TIME_SKEW_TOLERANCE = 3600000 // seconds (1 hour) - private const val TIME_SKEW_TOLERANCE_COINJOIN = 4000 // seconds + private const val TIME_SKEW_AHEAD_TOLERANCE_COINJOIN = 5000 // 5 seconds + private const val TIME_SKEW_BEHIND_TOLERANCE_COINJOIN = 20000 // 20 seconds + private val log = LoggerFactory.getLogger(MainViewModel::class.java) } @@ -392,10 +392,11 @@ class MainViewModel @Inject constructor( val maxAllowedTimeSkew = if (coinJoinConfig.getMode() == CoinJoinMode.NONE) { TIME_SKEW_TOLERANCE } else { - TIME_SKEW_TOLERANCE_COINJOIN + if (timeSkew > 0) TIME_SKEW_AHEAD_TOLERANCE_COINJOIN else TIME_SKEW_BEHIND_TOLERANCE_COINJOIN } coinJoinService.updateTimeSkew(timeSkew) - return Pair(timeSkew > maxAllowedTimeSkew, timeSkew) + log.info("timeskew: {} ms", timeSkew) + return Pair(kotlin.math.abs(timeSkew) > maxAllowedTimeSkew, timeSkew) } catch (ex: Exception) { // Ignore errors Pair(false, 0) diff --git a/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt b/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt index 301e5b4d67..28e1a68115 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/WalletActivityExt.kt @@ -45,6 +45,7 @@ import org.dash.wallet.common.services.analytics.AnalyticsConstants import org.dash.wallet.common.ui.dialogs.AdaptiveDialog import org.dash.wallet.common.ui.dialogs.AdaptiveDialog.Companion.create import org.dash.wallet.common.util.openCustomTab +import kotlin.math.abs object WalletActivityExt { private const val STORAGE_TOLERANCE = 500 // MB @@ -101,7 +102,7 @@ object WalletActivityExt { if (isTimeSkewed && (!timeSkewDialogShown || coinJoinOn)) { timeSkewDialogShown = true // add 1 to round up so 2.2 seconds appears as 3 - showTimeSkewAlertDialog(1 + timeSkew / 1000, coinJoinOn) + showTimeSkewAlertDialog((if (timeSkew > 0) 1 else -1) + timeSkew / 1000L, coinJoinOn) } } } @@ -179,7 +180,8 @@ object WalletActivityExt { R.drawable.ic_warning, getString(R.string.wallet_timeskew_dialog_title), if (coinJoin) { - getString(R.string.wallet_coinjoin_timeskew_dialog_msg, diffSeconds) + val position = getString(if (diffSeconds > 0) R.string.timeskew_ahead else R.string.timeskew_behind) + getString(R.string.wallet_coinjoin_timeskew_dialog_msg, position, abs(diffSeconds)) } else { getString(R.string.wallet_timeskew_dialog_msg, diffSeconds / 1000) }, diff --git a/wallet/src/de/schildbach/wallet/util/TimeUtils.kt b/wallet/src/de/schildbach/wallet/util/TimeUtils.kt index 4a9a7fef87..0d1c7fda41 100644 --- a/wallet/src/de/schildbach/wallet/util/TimeUtils.kt +++ b/wallet/src/de/schildbach/wallet/util/TimeUtils.kt @@ -54,5 +54,5 @@ suspend fun getTimeSkew(): Long { requireNotNull(networkTime) } val systemTimeMillis = System.currentTimeMillis() - return abs(systemTimeMillis - networkTime) + return systemTimeMillis - networkTime }