Update LibMobileCoin to 1.2.2.1

Fixes #12354

Co-authored-by: Bernie Dolan <bernie@mobilecoin.com>
Co-authored-by: Varsha <varsha@mobilecoin.com>
This commit is contained in:
Alex Hart
2022-07-29 15:59:52 -03:00
committed by Greyson Parrelli
parent 49cc962bde
commit f05f9287c1
8 changed files with 175 additions and 55 deletions

View File

@@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.mobilecoin.lib.exceptions.FogSyncException;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.PaymentDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
@@ -54,7 +56,7 @@ public final class PaymentLedgerUpdateJob extends BaseJob {
}
@Override
protected void onRun() throws IOException, RetryLaterException {
protected void onRun() throws IOException, RetryLaterException, FogSyncException {
if (!SignalStore.paymentsValues().mobileCoinPaymentsEnabled()) {
Log.w(TAG, "Payments are not enabled");
return;

View File

@@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
import com.mobilecoin.lib.ClientConfig;
import com.mobilecoin.lib.Verifier;
import com.mobilecoin.lib.exceptions.AttestationException;
import com.mobilecoin.lib.util.Hex;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.Base64;
@@ -65,31 +64,39 @@ final class MobileCoinMainNetConfig extends MobileCoinConfig {
@Override
@NonNull ClientConfig getConfig() {
try {
byte[] mrEnclaveConsensus = Hex.toByteArray("e66db38b8a43a33f6c1610d335a361963bb2b31e056af0dc0a895ac6c857cab9");
byte[] mrEnclaveConsensusNew = Hex.toByteArray("653228afd2b02a6c28f1dc3b108b1dfa457d170b32ae8ec2978f941bd1655c83");
byte[] mrEnclaveReport = Hex.toByteArray("709ab90621e3a8d9eb26ed9e2830e091beceebd55fb01c5d7c31d27e83b9b0d1");
byte[] mrEnclaveReportNew = Hex.toByteArray("f3f7e9a674c55fb2af543513527b6a7872de305bac171783f6716a0bf6919499");
byte[] mrEnclaveLedger = Hex.toByteArray("511eab36de691ded50eb08b173304194da8b9d86bfdd7102001fe6bb279c3666");
byte[] mrEnclaveLedgerNew = Hex.toByteArray("89db0d1684fcc98258295c39f4ab68f7de5917ef30f0004d9a86f29930cebbbd");
byte[] mrEnclaveView = Hex.toByteArray("ddd59da874fdf3239d5edb1ef251df07a8728c9ef63057dd0b50ade5a9ddb041");
byte[] mrEnclaveViewNew = Hex.toByteArray("dd84abda7f05116e21fcd1ee6361b0ec29445fff0472131eaf37bf06255b567a");
Set<X509Certificate> trustRoots = getTrustRoots(R.raw.signal_mobilecoin_authority);
ClientConfig config = new ClientConfig();
String[] hardeningAdvisories = { "INTEL-SA-00334" };
VerifierFactory verifierFactory = new VerifierFactory(hardeningAdvisories,
new ServiceConfig(
"e66db38b8a43a33f6c1610d335a361963bb2b31e056af0dc0a895ac6c857cab9",
"709ab90621e3a8d9eb26ed9e2830e091beceebd55fb01c5d7c31d27e83b9b0d1",
"511eab36de691ded50eb08b173304194da8b9d86bfdd7102001fe6bb279c3666",
"ddd59da874fdf3239d5edb1ef251df07a8728c9ef63057dd0b50ade5a9ddb041"
),
new ServiceConfig(
"653228afd2b02a6c28f1dc3b108b1dfa457d170b32ae8ec2978f941bd1655c83",
"f3f7e9a674c55fb2af543513527b6a7872de305bac171783f6716a0bf6919499",
"89db0d1684fcc98258295c39f4ab68f7de5917ef30f0004d9a86f29930cebbbd",
"dd84abda7f05116e21fcd1ee6361b0ec29445fff0472131eaf37bf06255b567a"
),
new ServiceConfig(
"733080d6ece4504f66ba606fa8163dae0a5220f3dbf6ca55fbafbac12c6f1897",
"660103d766cde0fd1e1cfb443b99e52da2ce0617d0dee42f8b875f7104942c6b",
"ed8ed6e1b4b6827e5543b25c1c13b9c06b478d819f8df912eb11fa140780fc51",
"c64a3b04348b10596442868758875f312dc3a755b450805149774a091d2822d3"
));
config.logAdapter = new MobileCoinLogAdapter();
config.fogView = new ClientConfig.Service().withTrustRoots(trustRoots)
.withVerifier(new Verifier().withMrEnclave(mrEnclaveView, null, hardeningAdvisories)
.withMrEnclave(mrEnclaveViewNew, null, hardeningAdvisories));
.withVerifier(verifierFactory.createViewVerifier());
config.fogLedger = new ClientConfig.Service().withTrustRoots(trustRoots)
.withVerifier(new Verifier().withMrEnclave(mrEnclaveLedger, null, hardeningAdvisories)
.withMrEnclave(mrEnclaveLedgerNew, null, hardeningAdvisories));
.withVerifier(verifierFactory.createLedgerVerifier());
config.consensus = new ClientConfig.Service().withTrustRoots(trustRoots)
.withVerifier(new Verifier().withMrEnclave(mrEnclaveConsensus, null, hardeningAdvisories)
.withMrEnclave(mrEnclaveConsensusNew, null, hardeningAdvisories));
config.report = new ClientConfig.Service().withVerifier(new Verifier().withMrEnclave(mrEnclaveReport, null, hardeningAdvisories)
.withMrEnclave(mrEnclaveReportNew, null, hardeningAdvisories));
.withVerifier(verifierFactory.createConsensusVerifier());
config.report = new ClientConfig.Service().withVerifier(verifierFactory.createReportVerifier());
return config;
} catch (AttestationException ex) {
throw new IllegalStateException();

View File

@@ -49,18 +49,7 @@ final class MobileCoinTestNetConfig extends MobileCoinConfig {
@Override
@NonNull byte[] getFogAuthoritySpki() {
return Base64.decodeOrThrow("MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoCMq8nnjTq5EEQ4EI7yr\n"
+ "ABL9P4y4h1P/h0DepWgXx+w/fywcfRSZINxbaMpvcV3uSJayExrpV1KmaS2wfASe\n"
+ "YhSj+rEzAm0XUOw3Q94NOx5A/dOQag/d1SS6/QpF3PQYZTULnRFetmM4yzEnXsXc\n"
+ "WtzEu0hh02wYJbLeAq4CCcPTPe2qckrbUP9sD18/KOzzNeypF4p5dQ2m/ezfxtga\n"
+ "LvdUMVDVIAs2v9a5iu6ce4bIcwTIUXgX0w3+UKRx8zqowc3HIqo9yeaGn4ZOwQHv\n"
+ "AJZecPmb2pH1nK+BtDUvHpvf+Y3/NJxwh+IPp6Ef8aoUxs2g5oIBZ3Q31fjS2Bh2\n"
+ "gmwoVooyytEysPAHvRPVBxXxLi36WpKfk1Vq8K7cgYh3IraOkH2/l2Pyi8EYYFkW\n"
+ "sLYofYogaiPzVoq2ZdcizfoJWIYei5mgq+8m0ZKZYLebK1i2GdseBJNIbSt3wCNX\n"
+ "ZxyN6uqFHOCB29gmA5cbKvs/j9mDz64PJe9LCanqcDQV1U5l9dt9UdmUt7Ab1PjB\n"
+ "toIFaP+u473Z0hmZdCgAivuiBMMYMqt2V2EIw4IXLASE3roLOYp0p7h0IQHb+lVI\n"
+ "uEl0ZmwAI30ZmzgcWc7RBeWD1/zNt55zzhfPRLx/DfDY5Kdp6oFHWMvI2r1/oZkd\n"
+ "hjFp7pV6qrl7vOyR5QqmuRkCAwEAAQ==");
return Base64.decodeOrThrow("MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoCMq8nnjTq5EEQ4EI7yrABL9P4y4h1P/h0DepWgXx+w/fywcfRSZINxbaMpvcV3uSJayExrpV1KmaS2wfASeYhSj+rEzAm0XUOw3Q94NOx5A/dOQag/d1SS6/QpF3PQYZTULnRFetmM4yzEnXsXcWtzEu0hh02wYJbLeAq4CCcPTPe2qckrbUP9sD18/KOzzNeypF4p5dQ2m/ezfxtgaLvdUMVDVIAs2v9a5iu6ce4bIcwTIUXgX0w3+UKRx8zqowc3HIqo9yeaGn4ZOwQHvAJZecPmb2pH1nK+BtDUvHpvf+Y3/NJxwh+IPp6Ef8aoUxs2g5oIBZ3Q31fjS2Bh2gmwoVooyytEysPAHvRPVBxXxLi36WpKfk1Vq8K7cgYh3IraOkH2/l2Pyi8EYYFkWsLYofYogaiPzVoq2ZdcizfoJWIYei5mgq+8m0ZKZYLebK1i2GdseBJNIbSt3wCNXZxyN6uqFHOCB29gmA5cbKvs/j9mDz64PJe9LCanqcDQV1U5l9dt9UdmUt7Ab1PjBtoIFaP+u473Z0hmZdCgAivuiBMMYMqt2V2EIw4IXLASE3roLOYp0p7h0IQHb+lVIuEl0ZmwAI30ZmzgcWc7RBeWD1/zNt55zzhfPRLx/DfDY5Kdp6oFHWMvI2r1/oZkdhjFp7pV6qrl7vOyR5QqmuRkCAwEAAQ==");
}
@Override
@@ -71,10 +60,10 @@ final class MobileCoinTestNetConfig extends MobileCoinConfig {
@Override
@NonNull ClientConfig getConfig() {
try {
byte[] mrEnclaveConsensus = Hex.toByteArray("9659ea738275b3999bf1700398b60281be03af5cb399738a89b49ea2496595af");
byte[] mrEnclaveReport = Hex.toByteArray("a4764346f91979b4906d4ce26102228efe3aba39216dec1e7d22e6b06f919f11");
byte[] mrEnclaveLedger = Hex.toByteArray("768f7bea6171fb83d775ee8485e4b5fcebf5f664ca7e8b9ceef9c7c21e9d9bf3");
byte[] mrEnclaveView = Hex.toByteArray("e154f108c7758b5aa7161c3824c176f0c20f63012463bf3cc5651e678f02fb9e");
byte[] mrEnclaveConsensus = Hex.toByteArray("4f134dcfd9c0885956f2f9af0f05c2050d8bdee2dc63b468a640670d7adeb7f8");
byte[] mrEnclaveReport = Hex.toByteArray("8f2f3bf81f24bf493fa6d76e29e0f081815022592b1e854f95bda750aece7452");
byte[] mrEnclaveLedger = Hex.toByteArray("685481b33f2846585f33506ab65649c98a4a6d1244989651fd0fcde904ebd82f");
byte[] mrEnclaveView = Hex.toByteArray("719ca43abbe02f507bb91ea11ff8bc900aa86363a7d7e77b8130426fc53d8684");
byte[] mrSigner = Hex.toByteArray("bf7fa957a6a94acb588851bc8767e0ca57706c79f4fc2aa6bcb993012c3c386c");
Set<X509Certificate> trustRoots = getTrustRoots(R.raw.signal_mobilecoin_authority);
ClientConfig config = new ClientConfig();

View File

@@ -0,0 +1,19 @@
package org.thoughtcrime.securesms.payments
import com.mobilecoin.lib.util.Hex
/**
* Represents the service configuration values for a given MobileCoin config, used to build
* Verifiers.
*/
class ServiceConfig(
consensus: String,
report: String,
ledger: String,
view: String
) {
val consensus: ByteArray = Hex.toByteArray(consensus)
val report: ByteArray = Hex.toByteArray(report)
val ledger: ByteArray = Hex.toByteArray(ledger)
val view: ByteArray = Hex.toByteArray(view)
}

View File

@@ -0,0 +1,39 @@
package org.thoughtcrime.securesms.payments
import com.mobilecoin.lib.Verifier
import com.mobilecoin.lib.exceptions.AttestationException
/**
* Wraps the given service configurations and provides methods to grab a fully constructed verifier instance.
* This is to ease the addition of new service configurations moving forward, which simply need a new ServiceConfig object
* to be added to the given list.
*/
class VerifierFactory(private val hardeningAdvisories: Array<String>, private vararg val serviceConfigs: ServiceConfig) {
@Throws(AttestationException::class)
fun createConsensusVerifier(): Verifier {
return createVerifier(ServiceConfig::consensus)
}
@Throws(AttestationException::class)
fun createLedgerVerifier(): Verifier {
return createVerifier(ServiceConfig::ledger)
}
@Throws(AttestationException::class)
fun createViewVerifier(): Verifier {
return createVerifier(ServiceConfig::view)
}
@Throws(AttestationException::class)
fun createReportVerifier(): Verifier {
return createVerifier(ServiceConfig::report)
}
@Throws(AttestationException::class)
private fun createVerifier(getConfigValue: (ServiceConfig) -> ByteArray): Verifier {
return serviceConfigs.fold(Verifier()) { verifier, config ->
verifier.withMrEnclave(getConfigValue(config), null, hardeningAdvisories)
}
}
}

View File

@@ -8,18 +8,22 @@ import androidx.annotation.WorkerThread;
import com.google.protobuf.ByteString;
import com.mobilecoin.lib.AccountKey;
import com.mobilecoin.lib.AccountSnapshot;
import com.mobilecoin.lib.Amount;
import com.mobilecoin.lib.DefragmentationDelegate;
import com.mobilecoin.lib.MobileCoinClient;
import com.mobilecoin.lib.OwnedTxOut;
import com.mobilecoin.lib.PendingTransaction;
import com.mobilecoin.lib.Receipt;
import com.mobilecoin.lib.TokenId;
import com.mobilecoin.lib.Transaction;
import com.mobilecoin.lib.TxOutMemoBuilder;
import com.mobilecoin.lib.UnsignedLong;
import com.mobilecoin.lib.exceptions.AmountDecoderException;
import com.mobilecoin.lib.exceptions.AttestationException;
import com.mobilecoin.lib.exceptions.BadEntropyException;
import com.mobilecoin.lib.exceptions.FeeRejectedException;
import com.mobilecoin.lib.exceptions.FogReportException;
import com.mobilecoin.lib.exceptions.FogSyncException;
import com.mobilecoin.lib.exceptions.FragmentedAccountException;
import com.mobilecoin.lib.exceptions.InsufficientFundsException;
import com.mobilecoin.lib.exceptions.InvalidFogResponse;
@@ -29,6 +33,7 @@ import com.mobilecoin.lib.exceptions.InvalidUriException;
import com.mobilecoin.lib.exceptions.NetworkException;
import com.mobilecoin.lib.exceptions.SerializationException;
import com.mobilecoin.lib.exceptions.TransactionBuilderException;
import com.mobilecoin.lib.network.TransportProtocol;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.keyvalue.PaymentsValues;
@@ -65,7 +70,8 @@ public final class Wallet {
this.mobileCoinClient = new MobileCoinClient(account,
mobileCoinConfig.getFogUri(),
mobileCoinConfig.getConsensusUri(),
mobileCoinConfig.getConfig());
mobileCoinConfig.getConfig(),
TransportProtocol.forGRPC());
} catch (InvalidUriException | BadEntropyException e) {
throw new AssertionError(e);
}
@@ -102,7 +108,7 @@ public final class Wallet {
MobileCoinLedgerWrapper ledger = tryGetFullLedger(null);
paymentsValues.setMobileCoinFullLedger(Objects.requireNonNull(ledger));
} catch (IOException e) {
} catch (IOException | FogSyncException e) {
if ((retryOnAuthFailure && e.getCause() instanceof NetworkException) &&
(((NetworkException) e.getCause()).statusCode == 401))
{
@@ -117,7 +123,7 @@ public final class Wallet {
}
@WorkerThread
public @Nullable MobileCoinLedgerWrapper tryGetFullLedger(@Nullable Long minimumBlockIndex) throws IOException {
public @Nullable MobileCoinLedgerWrapper tryGetFullLedger(@Nullable Long minimumBlockIndex) throws IOException, FogSyncException {
try {
MobileCoinLedger.Builder builder = MobileCoinLedger.newBuilder();
BigInteger totalUnspent = BigInteger.ZERO;
@@ -125,7 +131,7 @@ public final class Wallet {
UnsignedLong highestBlockIndex = UnsignedLong.ZERO;
final long asOfTimestamp = System.currentTimeMillis();
AccountSnapshot accountSnapshot = mobileCoinClient.getAccountSnapshot();
final BigInteger minimumTxFee = mobileCoinClient.getOrFetchMinimumTxFee();
final Amount minimumTxFee = mobileCoinClient.getOrFetchMinimumTxFee(TokenId.MOB);
if (minimumBlockIndex != null) {
long snapshotBlockIndex = accountSnapshot.getBlockIndex().longValue();
@@ -135,9 +141,10 @@ public final class Wallet {
}
}
for (OwnedTxOut txOut : accountSnapshot.getAccountActivity().getAllTxOuts()) {
for (OwnedTxOut txOut : accountSnapshot.getAccountActivity().getAllTokenTxOuts(TokenId.MOB)) {
final Amount txOutAmount = txOut.getAmount();
MobileCoinLedger.OwnedTXO.Builder txoBuilder = MobileCoinLedger.OwnedTXO.newBuilder()
.setAmount(Uint64Util.bigIntegerToUInt64(txOut.getValue()))
.setAmount(Uint64Util.bigIntegerToUInt64(txOutAmount.getValue()))
.setReceivedInBlock(getBlock(txOut.getReceivedBlockIndex(), txOut.getReceivedBlockTimestamp()))
.setKeyImage(ByteString.copyFrom(txOut.getKeyImage().getData()))
.setPublicKey(ByteString.copyFrom(txOut.getPublicKey().getKeyBytes()));
@@ -147,7 +154,7 @@ public final class Wallet {
txoBuilder.setSpentInBlock(getBlock(txOut.getSpentBlockIndex(), txOut.getSpentBlockTimestamp()));
builder.addSpentTxos(txoBuilder);
} else {
totalUnspent = totalUnspent.add(txOut.getValue());
totalUnspent = totalUnspent.add(txOutAmount.getValue());
builder.addUnspentTxos(txoBuilder);
}
@@ -168,7 +175,7 @@ public final class Wallet {
}
}
builder.setBalance(Uint64Util.bigIntegerToUInt64(totalUnspent))
.setTransferableBalance(Uint64Util.bigIntegerToUInt64(accountSnapshot.getTransferableAmount(minimumTxFee)))
.setTransferableBalance(Uint64Util.bigIntegerToUInt64(accountSnapshot.getTransferableAmount(minimumTxFee).getValue()))
.setAsOfTimeStamp(asOfTimestamp)
.setHighestBlock(MobileCoinLedger.Block.newBuilder()
.setBlockNumber(highestBlockIndex.longValue())
@@ -206,11 +213,11 @@ public final class Wallet {
public @NonNull Money.MobileCoin getFee(@NonNull Money.MobileCoin amount) throws IOException {
try {
BigInteger picoMob = amount.requireMobileCoin().toPicoMobBigInteger();
return Money.picoMobileCoin(mobileCoinClient.estimateTotalFee(picoMob));
return Money.picoMobileCoin(mobileCoinClient.estimateTotalFee(Amount.ofMOB(picoMob)).getValue());
} catch (InvalidFogResponse | AttestationException | InsufficientFundsException e) {
Log.w(TAG, "Failed to get fee", e);
return Money.MobileCoin.ZERO;
} catch (NetworkException e) {
} catch (NetworkException | FogSyncException e) {
Log.w(TAG, "Failed to get fee", e);
throw new IOException(e);
}
@@ -227,7 +234,7 @@ public final class Wallet {
}
@WorkerThread
public @NonNull TransactionStatusResult getSentTransactionStatus(@NonNull PaymentTransactionId transactionId) throws IOException {
public @NonNull TransactionStatusResult getSentTransactionStatus(@NonNull PaymentTransactionId transactionId) throws IOException, FogSyncException {
try {
PaymentTransactionId.MobileCoin mobcoinTransaction = (PaymentTransactionId.MobileCoin) transactionId;
Transaction transaction = Transaction.fromBytes(mobcoinTransaction.getTransaction());
@@ -255,7 +262,7 @@ public final class Wallet {
}
@WorkerThread
public @NonNull ReceivedTransactionStatus getReceivedTransactionStatus(@NonNull byte[] receiptBytes) throws IOException {
public @NonNull ReceivedTransactionStatus getReceivedTransactionStatus(@NonNull byte[] receiptBytes) throws IOException, FogSyncException {
try {
Receipt receipt = Receipt.fromBytes(receiptBytes);
Receipt.Status status = mobileCoinClient.getReceiptStatus(receipt);
@@ -266,8 +273,8 @@ public final class Wallet {
case FAILED:
return ReceivedTransactionStatus.failed();
case RECEIVED:
BigInteger amount = receipt.getAmount(account);
return ReceivedTransactionStatus.complete(Money.picoMobileCoin(amount), status.getBlockIndex().longValue());
final Amount amount = receipt.getAmountData(account);
return ReceivedTransactionStatus.complete(Money.picoMobileCoin(amount.getValue()), status.getBlockIndex().longValue());
default:
throw new IllegalStateException("Unknown Transaction Status: " + status);
}
@@ -297,7 +304,7 @@ public final class Wallet {
Log.w(TAG, "Insufficient funds", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.INSUFFICIENT_FUNDS, true));
return;
} catch (TimeoutException | InvalidTransactionException | InvalidFogResponse | AttestationException | TransactionBuilderException | NetworkException | FogReportException e) {
} catch (TimeoutException | InvalidTransactionException | InvalidFogResponse | AttestationException | TransactionBuilderException | NetworkException | FogReportException | FogSyncException e) {
Log.w(TAG, "Defragment failed", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.GENERIC_FAILURE, true));
return;
@@ -318,8 +325,9 @@ public final class Wallet {
try {
pendingTransaction = mobileCoinClient.prepareTransaction(to.getAddress(),
picoMob,
feeMobileCoin.toPicoMobBigInteger());
Amount.ofMOB(picoMob),
Amount.ofMOB(feeMobileCoin.toPicoMobBigInteger()),
TxOutMemoBuilder.createSenderAndDestinationRTHMemoBuilder(account));
} catch (InsufficientFundsException e) {
Log.w(TAG, "Insufficient funds", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.INSUFFICIENT_FUNDS, false));
@@ -346,6 +354,9 @@ public final class Wallet {
} catch (TransactionBuilderException e) {
Log.w(TAG, "Builder problem", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.GENERIC_FAILURE, false));
} catch(FogSyncException e) {
Log.w(TAG, "Fog currently out of sync", e);
results.add(TransactionSubmissionResult.failure(TransactionSubmissionResult.ErrorCode.NETWORK_FAILURE, false));
}
if (pendingTransaction == null) {
@@ -379,11 +390,11 @@ public final class Wallet {
*/
@WorkerThread
private @NonNull Money.MobileCoin defragment(@NonNull Money.MobileCoin amount, @NonNull List<TransactionSubmissionResult> results)
throws TransactionBuilderException, NetworkException, InvalidTransactionException, AttestationException, FogReportException, InvalidFogResponse, TimeoutException, InsufficientFundsException
throws TransactionBuilderException, NetworkException, InvalidTransactionException, AttestationException, FogReportException, InvalidFogResponse, TimeoutException, InsufficientFundsException, FogSyncException
{
Log.i(TAG, "Defragmenting account");
DefragDelegate defragDelegate = new DefragDelegate(mobileCoinClient, results);
mobileCoinClient.defragmentAccount(amount.toPicoMobBigInteger(), defragDelegate);
mobileCoinClient.defragmentAccount(Amount.ofMOB(amount.toPicoMobBigInteger()), defragDelegate, true);
Log.i(TAG, "Account defragmented at a cost of " + defragDelegate.totalFeesSpent);
return defragDelegate.totalFeesSpent;
}

View File

@@ -92,7 +92,7 @@ dependencyResolutionManagement {
alias('rxjava3-rxkotlin').to('io.reactivex.rxjava3:rxkotlin:3.0.1')
alias('rxdogtag').to('com.uber.rxdogtag2:rxdogtag:2.0.1')
alias('conscrypt-android').to('org.conscrypt:conscrypt-android:2.0.0')
alias('mobilecoin').to('com.mobilecoin:android-sdk:1.1.0')
alias('mobilecoin').to('com.mobilecoin:android-sdk:1.2.2.1')
alias('leolin-shortcutbadger').to('me.leolin:ShortcutBadger:1.1.22')
alias('emilsjolander-stickylistheaders').to('se.emilsjolander:stickylistheaders:2.7.0')
alias('jpardogo-materialtabstrip').to('com.jpardogo.materialtabstrip:library:1.0.9')

View File

@@ -73,6 +73,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="2efcab81ef91b211bacd206eaacd995a51f633a2e96b57a8fc00144c5f9c56b3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.annotation" name="annotation" version="1.3.0">
<artifact name="annotation-1.3.0.jar">
<sha256 value="97dc45afefe3a1e421da42b8b6e9f90491477c45fc6178203e3a5e8a05ee8553" origin="Generated by Gradle"/>
</artifact>
<artifact name="annotation-1.3.0.module">
<sha256 value="9516c2ae44284ea0bd3d0eade0ee638879b708cbe31e3af92ba96c300604ebc3" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.annotation" name="annotation-experimental" version="1.0.0">
<artifact name="annotation-experimental-1.0.0.aar">
<sha256 value="b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11" origin="Generated by Gradle"/>
@@ -2505,6 +2513,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="3f562c14bdc3a17fb54da5e7beb6b6f8acf1848b580e68c90bfc4d797ce68fc2" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.guava" name="guava" version="30.1-android">
<artifact name="guava-30.1-android.jar">
<sha256 value="ea0b5a62b707482eee5cf305c8f35ef91cf4ceaff504f011a5c49c41355f5781" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.google.guava" name="guava" version="30.1-jre">
<artifact name="guava-30.1-jre.jar">
<sha256 value="e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa" origin="Generated by Gradle"/>
@@ -2814,6 +2827,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="2b5f87a296d744f441942e3dfa2909da0a604dc3e9645e278d1a1a9aec347681" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.mobilecoin" name="android-bindings" version="1.2.2">
<artifact name="android-bindings-1.2.2.aar">
<sha256 value="7f61d95d2616b0a39dc7449419102534f550d173f0721a3876546b7bdc746d34" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.mobilecoin" name="android-sdk" version="1.1.0">
<artifact name="android-sdk-1.1.0.aar">
<sha256 value="a57b73613c8fb255bf735d910268f945a6c690ff24d45cc6034aa34e9a3ae4d5" origin="Generated by Gradle"/>
@@ -2822,6 +2840,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="7fc994d96346cde37767c428b115473ec3444c6cb9509673b120d572b4c4b8ec" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.mobilecoin" name="android-sdk" version="1.2.2.1">
<artifact name="android-sdk-1.2.2.1.aar">
<sha256 value="25434813eef31de5f7b2d11bb744b8434be3750e3010fc9803e54671076f071d" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest" name="ktlint" version="0.43.2">
<artifact name="ktlint-0.43.2.jar">
<sha256 value="99ec69ef0628695c24dbbc2cc4b8d7c61a754697d624f5233fc65f43faf2d235" origin="Generated by Gradle"/>
@@ -3344,6 +3367,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="ef90c4c9a9c653919f36ed9f43218d7a96ce6e50a58c561a8bfc47bad97d6c55" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-api" version="1.38.0">
<artifact name="grpc-api-1.38.0.jar">
<sha256 value="0613290eca34cf034abf68d6556196239b612a8ba7182fde42d772147b3287c6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-context" version="1.21.1">
<artifact name="grpc-context-1.21.1.jar">
<sha256 value="a93fea132d401f5ab90f5bf520c550bc81423bfcf4a7998ade9db879dcd78207" origin="Generated by Gradle"/>
@@ -3360,6 +3388,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="fb8bf4b895dc39346f2eb0771025c66266b30759baa5f03ba5658e66fde6d695" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-context" version="1.38.0">
<artifact name="grpc-context-1.38.0.jar">
<sha256 value="681bcfa0c546336b42594b9547b75d93ae84925bb48ed22f5dd7c936e9efe285" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-core" version="1.21.1">
<artifact name="grpc-core-1.21.1.jar">
<sha256 value="1506d0516168b68eedfaa6be1433c137a1e996a465496cfb54d54853cbc9028e" origin="Generated by Gradle"/>
@@ -3376,6 +3409,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="a5b036a13f13bc874869476bfc1325b1c7ca236cd9bb6aa7ac4d3b4f5adac620" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-core" version="1.38.0">
<artifact name="grpc-core-1.38.0.jar">
<sha256 value="265a83df9c29f5114e291316c0a7b1c0bcfdeb7e567eeff73a85238ec35e9e05" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-netty" version="1.21.1">
<artifact name="grpc-netty-1.21.1.jar">
<sha256 value="10435dbf5ede3ca7dd72432a81ff7d508f6b930bfd5fe228d1a59b57ffce9bc7" origin="Generated by Gradle"/>
@@ -3392,6 +3430,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="676704ac1a5e68451f70ea028087b6641fab572ea06d14d2eaaba511c78b9595" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-okhttp" version="1.38.0">
<artifact name="grpc-okhttp-1.38.0.jar">
<sha256 value="ae91ebb7abed7825f782df6a9997d31448f643b80e51d36498ce356ca9ebf0e4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-protobuf" version="1.21.1">
<artifact name="grpc-protobuf-1.21.1.jar">
<sha256 value="c9c0070c39f95e9d7acad60fdcc3d4c91729a4c12cde15705099b09e201abc01" origin="Generated by Gradle"/>
@@ -3416,6 +3459,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="08d71c574710637a3e0a648ab349f4c52459ea06d1bad1cb4ffacc4d785aaa9c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-protobuf-lite" version="1.38.0">
<artifact name="grpc-protobuf-lite-1.38.0.jar">
<sha256 value="9f97d178827123d838b9a7b8a73f31f6d747a4e4fac998a4f7c13612aaa93979" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-stub" version="1.21.1">
<artifact name="grpc-stub-1.21.1.jar">
<sha256 value="642c328916291287e96702cc5ad1f7d601a0c347c9de0f130219aa0fdc7d5a90" origin="Generated by Gradle"/>
@@ -3432,6 +3480,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="adcdb8cec92195f916a7c4a5f9b8dd2a8228ae13b837562ea7a4897b2cb9e3c6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.grpc" name="grpc-stub" version="1.38.0">
<artifact name="grpc-stub-1.38.0.jar">
<sha256 value="a6a8701ed35259ead9c7fc86e855e26559050e0a60a3be66a8f5c327c53eeaf8" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.netty" name="netty-buffer" version="4.1.34.Final">
<artifact name="netty-buffer-4.1.34.Final.jar">
<sha256 value="39dfe88df8505fd01fbf9c1dbb6b6fa9b0297e453c3dc4ce039ea578aea2eaa3" origin="Generated by Gradle"/>