mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Convert SignalService, Database, Group, Payment, and other remaining protos to wire.
This commit is contained in:
committed by
Alex Hart
parent
a6b7d0bcc5
commit
efbd5cab85
@@ -16,28 +16,21 @@ public final class CryptoValueUtil {
|
||||
}
|
||||
|
||||
public static @NonNull CryptoValue moneyToCryptoValue(@NonNull Money money) {
|
||||
CryptoValue.Builder builder = CryptoValue.newBuilder();
|
||||
CryptoValue.Builder builder = new CryptoValue.Builder();
|
||||
|
||||
if (money instanceof Money.MobileCoin) {
|
||||
Money.MobileCoin mobileCoin = (Money.MobileCoin) money;
|
||||
builder.setMobileCoinValue(CryptoValue.MobileCoinValue
|
||||
.newBuilder()
|
||||
.setPicoMobileCoin(mobileCoin.serializeAmountString()));
|
||||
builder.mobileCoinValue(new CryptoValue.MobileCoinValue.Builder().picoMobileCoin(mobileCoin.serializeAmountString()).build());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static @NonNull Money cryptoValueToMoney(@NonNull CryptoValue amount) {
|
||||
CryptoValue.ValueCase valueCase = amount.getValueCase();
|
||||
|
||||
switch (valueCase) {
|
||||
case MOBILECOINVALUE:
|
||||
return Money.picoMobileCoin(new BigInteger(amount.getMobileCoinValue().getPicoMobileCoin()));
|
||||
case VALUE_NOT_SET:
|
||||
throw new AssertionError();
|
||||
if (amount.mobileCoinValue != null) {
|
||||
return Money.picoMobileCoin(new BigInteger(amount.mobileCoinValue.picoMobileCoin));
|
||||
} else {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package org.thoughtcrime.securesms.payments;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.payments.proto.MobileCoinLedger;
|
||||
import org.whispersystems.signalservice.api.payments.Money;
|
||||
|
||||
@@ -12,17 +10,19 @@ import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public final class MobileCoinLedgerWrapper {
|
||||
|
||||
private final MobileCoinLedger ledger;
|
||||
private final Balance balance;
|
||||
|
||||
public MobileCoinLedgerWrapper(@NonNull MobileCoinLedger ledger) {
|
||||
Money.MobileCoin fullAmount = Money.picoMobileCoin(ledger.getBalance());
|
||||
Money.MobileCoin transferableAmount = Money.picoMobileCoin(ledger.getTransferableBalance());
|
||||
Money.MobileCoin fullAmount = Money.picoMobileCoin(ledger.balance);
|
||||
Money.MobileCoin transferableAmount = Money.picoMobileCoin(ledger.transferableBalance);
|
||||
|
||||
this.ledger = ledger;
|
||||
this.balance = new Balance(fullAmount, transferableAmount, ledger.getAsOfTimeStamp());
|
||||
this.balance = new Balance(fullAmount, transferableAmount, ledger.asOfTimeStamp);
|
||||
}
|
||||
|
||||
public @NonNull Balance getBalance() {
|
||||
@@ -30,13 +30,13 @@ public final class MobileCoinLedgerWrapper {
|
||||
}
|
||||
|
||||
public byte[] serialize() {
|
||||
return ledger.toByteArray();
|
||||
return ledger.encode();
|
||||
}
|
||||
|
||||
public @NonNull List<OwnedTxo> getAllTxos() {
|
||||
List<OwnedTxo> txoList = new ArrayList<>(ledger.getSpentTxosCount() + ledger.getUnspentTxosCount());
|
||||
addAllMapped(txoList, ledger.getSpentTxosList());
|
||||
addAllMapped(txoList, ledger.getUnspentTxosList());
|
||||
List<OwnedTxo> txoList = new ArrayList<>(ledger.spentTxos.size() + ledger.unspentTxos.size());
|
||||
addAllMapped(txoList, ledger.spentTxos);
|
||||
addAllMapped(txoList, ledger.unspentTxos);
|
||||
return txoList;
|
||||
}
|
||||
|
||||
@@ -54,35 +54,35 @@ public final class MobileCoinLedgerWrapper {
|
||||
}
|
||||
|
||||
public @NonNull Money.MobileCoin getValue() {
|
||||
return Money.picoMobileCoin(ownedTXO.getAmount());
|
||||
return Money.picoMobileCoin(ownedTXO.amount);
|
||||
}
|
||||
|
||||
public @NonNull ByteString getKeyImage() {
|
||||
return ownedTXO.getKeyImage();
|
||||
return ownedTXO.keyImage;
|
||||
}
|
||||
|
||||
public @NonNull ByteString getPublicKey() {
|
||||
return ownedTXO.getPublicKey();
|
||||
return ownedTXO.publicKey;
|
||||
}
|
||||
|
||||
public long getReceivedInBlock() {
|
||||
return ownedTXO.getReceivedInBlock().getBlockNumber();
|
||||
return ownedTXO.receivedInBlock != null ? ownedTXO.receivedInBlock.blockNumber : 0;
|
||||
}
|
||||
|
||||
public @Nullable Long getSpentInBlock() {
|
||||
return nullIfZero(ownedTXO.getSpentInBlock().getBlockNumber());
|
||||
return ownedTXO.spentInBlock != null ? nullIfZero(ownedTXO.spentInBlock.blockNumber) : null;
|
||||
}
|
||||
|
||||
public boolean isSpent() {
|
||||
return ownedTXO.getSpentInBlock().getBlockNumber() != 0;
|
||||
return ownedTXO.spentInBlock != null && ownedTXO.spentInBlock.blockNumber != 0;
|
||||
}
|
||||
|
||||
public @Nullable Long getReceivedInBlockTimestamp() {
|
||||
return nullIfZero(ownedTXO.getReceivedInBlock().getTimestamp());
|
||||
return ownedTXO.receivedInBlock != null ? nullIfZero(ownedTXO.receivedInBlock.timestamp) : null;
|
||||
}
|
||||
|
||||
public @Nullable Long getSpentInBlockTimestamp() {
|
||||
return nullIfZero(ownedTXO.getSpentInBlock().getTimestamp());
|
||||
return ownedTXO.spentInBlock != null ? nullIfZero(ownedTXO.spentInBlock.timestamp) : null;
|
||||
}
|
||||
|
||||
private @Nullable Long nullIfZero(long value) {
|
||||
|
||||
@@ -2,11 +2,11 @@ package org.thoughtcrime.securesms.payments;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||
import org.whispersystems.signalservice.internal.push.PaymentAddress;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public final class MobileCoinPublicAddressProfileUtil {
|
||||
|
||||
@@ -15,16 +15,17 @@ public final class MobileCoinPublicAddressProfileUtil {
|
||||
/**
|
||||
* Signs the supplied address bytes with the {@link IdentityKeyPair}'s private key and returns a proto that includes it and it's signature.
|
||||
*/
|
||||
public static @NonNull SignalServiceProtos.PaymentAddress signPaymentsAddress(@NonNull byte[] publicAddressBytes,
|
||||
@NonNull IdentityKeyPair identityKeyPair)
|
||||
public static @NonNull PaymentAddress signPaymentsAddress(@NonNull byte[] publicAddressBytes,
|
||||
@NonNull IdentityKeyPair identityKeyPair)
|
||||
{
|
||||
byte[] signature = identityKeyPair.getPrivateKey().calculateSignature(publicAddressBytes);
|
||||
|
||||
return SignalServiceProtos.PaymentAddress.newBuilder()
|
||||
.setMobileCoinAddress(SignalServiceProtos.PaymentAddress.MobileCoinAddress.newBuilder()
|
||||
.setAddress(ByteString.copyFrom(publicAddressBytes))
|
||||
.setSignature(ByteString.copyFrom(signature)))
|
||||
.build();
|
||||
return new PaymentAddress.Builder()
|
||||
.mobileCoinAddress(new PaymentAddress.MobileCoinAddress.Builder()
|
||||
.address(ByteString.of(publicAddressBytes))
|
||||
.signature(ByteString.of(signature))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,16 +33,20 @@ public final class MobileCoinPublicAddressProfileUtil {
|
||||
* <p>
|
||||
* Returns the validated bytes if so, otherwise throws.
|
||||
*/
|
||||
public static @NonNull byte[] verifyPaymentsAddress(@NonNull SignalServiceProtos.PaymentAddress paymentAddress,
|
||||
public static @NonNull byte[] verifyPaymentsAddress(@NonNull PaymentAddress paymentAddress,
|
||||
@NonNull IdentityKey identityKey)
|
||||
throws PaymentsAddressException
|
||||
throws PaymentsAddressException
|
||||
{
|
||||
if (!paymentAddress.hasMobileCoinAddress()) {
|
||||
if (paymentAddress.mobileCoinAddress == null) {
|
||||
throw new PaymentsAddressException(PaymentsAddressException.Code.NO_ADDRESS);
|
||||
}
|
||||
|
||||
byte[] bytes = paymentAddress.getMobileCoinAddress().getAddress().toByteArray();
|
||||
byte[] signature = paymentAddress.getMobileCoinAddress().getSignature().toByteArray();
|
||||
if (paymentAddress.mobileCoinAddress.address == null || paymentAddress.mobileCoinAddress.signature == null) {
|
||||
throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE);
|
||||
}
|
||||
|
||||
byte[] bytes = paymentAddress.mobileCoinAddress.address.toByteArray();
|
||||
byte[] signature = paymentAddress.mobileCoinAddress.signature.toByteArray();
|
||||
|
||||
if (signature.length != 64 || !identityKey.getPublicKey().verifySignature(bytes, signature)) {
|
||||
throw new PaymentsAddressException(PaymentsAddressException.Code.INVALID_ADDRESS_SIGNATURE);
|
||||
|
||||
@@ -6,12 +6,11 @@ import android.os.Parcelable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.thoughtcrime.securesms.payments.preferences.model.PayeeParcelable;
|
||||
import org.thoughtcrime.securesms.payments.proto.PaymentMetaData;
|
||||
import org.whispersystems.signalservice.api.payments.Money;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -68,7 +67,7 @@ public class PaymentParcelable implements Parcelable {
|
||||
dest.writeString(payment.getNote());
|
||||
dest.writeString(payment.getAmount().serialize());
|
||||
dest.writeString(payment.getFee().serialize());
|
||||
dest.writeByteArray(payment.getPaymentMetaData().toByteArray());
|
||||
dest.writeByteArray(payment.getPaymentMetaData().encode());
|
||||
dest.writeByte(payment.isSeen() ? (byte) 1 : 0);
|
||||
dest.writeString(payment.getAmountWithDirection().serialize());
|
||||
dest.writeString(payment.getAmountPlusFeeWithDirection().serialize());
|
||||
@@ -119,12 +118,12 @@ public class PaymentParcelable implements Parcelable {
|
||||
note = in.readString();
|
||||
amount = Money.parse(in.readString());
|
||||
fee = Money.parse(in.readString());
|
||||
paymentMetaData = PaymentMetaData.parseFrom(in.createByteArray());
|
||||
paymentMetaData = PaymentMetaData.ADAPTER.decode(in.createByteArray());
|
||||
isSeen = in.readByte() == 1;
|
||||
amountWithDirection = Money.parse(in.readString());
|
||||
amountPlusFeeWithDirection = Money.parse(in.readString());
|
||||
isDefrag = in.readByte() == 1;
|
||||
} catch (Money.ParseException | InvalidProtocolBufferException e) {
|
||||
} catch (Money.ParseException | IOException e) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class ReconstructedPayment implements Payment {
|
||||
|
||||
@Override
|
||||
public @NonNull PaymentMetaData getPaymentMetaData() {
|
||||
return PaymentMetaData.getDefaultInstance();
|
||||
return new PaymentMetaData();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.mobilecoin.lib.AccountKey;
|
||||
import com.mobilecoin.lib.AccountSnapshot;
|
||||
import com.mobilecoin.lib.Amount;
|
||||
@@ -52,6 +51,8 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public final class Wallet {
|
||||
|
||||
private static final String TAG = Log.tag(Wallet.class);
|
||||
@@ -135,7 +136,7 @@ public final class Wallet {
|
||||
@WorkerThread
|
||||
public @Nullable MobileCoinLedgerWrapper tryGetFullLedger(@Nullable Long minimumBlockIndex) throws IOException, FogSyncException {
|
||||
try {
|
||||
MobileCoinLedger.Builder builder = MobileCoinLedger.newBuilder();
|
||||
MobileCoinLedger.Builder builder = new MobileCoinLedger.Builder();
|
||||
BigInteger totalUnspent = BigInteger.ZERO;
|
||||
long highestBlockTimeStamp = 0;
|
||||
UnsignedLong highestBlockIndex = UnsignedLong.ZERO;
|
||||
@@ -159,21 +160,23 @@ public final class Wallet {
|
||||
}
|
||||
}
|
||||
|
||||
List<MobileCoinLedger.OwnedTXO> spentTxos = new LinkedList<>();
|
||||
List<MobileCoinLedger.OwnedTXO> unspentTxos = new LinkedList<>();
|
||||
for (OwnedTxOut txOut : accountSnapshot.getAccountActivity().getAllTokenTxOuts(TokenId.MOB)) {
|
||||
final Amount txOutAmount = txOut.getAmount();
|
||||
MobileCoinLedger.OwnedTXO.Builder txoBuilder = MobileCoinLedger.OwnedTXO.newBuilder()
|
||||
.setAmount(Uint64Util.bigIntegerToUInt64(txOutAmount.getValue()))
|
||||
.setReceivedInBlock(getBlock(txOut.getReceivedBlockIndex(), txOut.getReceivedBlockTimestamp()))
|
||||
.setKeyImage(ByteString.copyFrom(txOut.getKeyImage().getData()))
|
||||
.setPublicKey(ByteString.copyFrom(txOut.getPublicKey().getKeyBytes()));
|
||||
MobileCoinLedger.OwnedTXO.Builder txoBuilder = new MobileCoinLedger.OwnedTXO.Builder()
|
||||
.amount(Uint64Util.bigIntegerToUInt64(txOutAmount.getValue()))
|
||||
.receivedInBlock(getBlock(txOut.getReceivedBlockIndex(), txOut.getReceivedBlockTimestamp()))
|
||||
.keyImage(ByteString.of(txOut.getKeyImage().getData()))
|
||||
.publicKey(ByteString.of(txOut.getPublicKey().getKeyBytes()));
|
||||
if (txOut.getSpentBlockIndex() != null &&
|
||||
(minimumBlockIndex == null || txOut.isSpent(UnsignedLong.valueOf(minimumBlockIndex))))
|
||||
{
|
||||
txoBuilder.setSpentInBlock(getBlock(txOut.getSpentBlockIndex(), txOut.getSpentBlockTimestamp()));
|
||||
builder.addSpentTxos(txoBuilder);
|
||||
txoBuilder.spentInBlock(getBlock(txOut.getSpentBlockIndex(), txOut.getSpentBlockTimestamp()));
|
||||
spentTxos.add(txoBuilder.build());
|
||||
} else {
|
||||
totalUnspent = totalUnspent.add(txOutAmount.getValue());
|
||||
builder.addUnspentTxos(txoBuilder);
|
||||
unspentTxos.add(txoBuilder.build());
|
||||
}
|
||||
|
||||
if (txOut.getSpentBlockIndex() != null && txOut.getSpentBlockIndex().compareTo(highestBlockIndex) > 0) {
|
||||
@@ -192,12 +195,16 @@ public final class Wallet {
|
||||
highestBlockTimeStamp = txOut.getReceivedBlockTimestamp().getTime();
|
||||
}
|
||||
}
|
||||
builder.setBalance(Uint64Util.bigIntegerToUInt64(totalUnspent))
|
||||
.setTransferableBalance(Uint64Util.bigIntegerToUInt64(accountSnapshot.getTransferableAmount(minimumTxFee).getValue()))
|
||||
.setAsOfTimeStamp(asOfTimestamp)
|
||||
.setHighestBlock(MobileCoinLedger.Block.newBuilder()
|
||||
.setBlockNumber(highestBlockIndex.longValue())
|
||||
.setTimestamp(highestBlockTimeStamp));
|
||||
|
||||
builder.spentTxos(spentTxos)
|
||||
.unspentTxos(unspentTxos)
|
||||
.balance(Uint64Util.bigIntegerToUInt64(totalUnspent))
|
||||
.transferableBalance(Uint64Util.bigIntegerToUInt64(accountSnapshot.getTransferableAmount(minimumTxFee).getValue()))
|
||||
.asOfTimeStamp(asOfTimestamp)
|
||||
.highestBlock(new MobileCoinLedger.Block.Builder()
|
||||
.blockNumber(highestBlockIndex.longValue())
|
||||
.timestamp(highestBlockTimeStamp)
|
||||
.build());
|
||||
SignalStore.paymentsValues().setEnclaveFailure(false);
|
||||
return new MobileCoinLedgerWrapper(builder.build());
|
||||
} catch (InvalidFogResponse e) {
|
||||
@@ -220,10 +227,10 @@ public final class Wallet {
|
||||
}
|
||||
|
||||
private static @Nullable MobileCoinLedger.Block getBlock(@NonNull UnsignedLong blockIndex, @Nullable Date timeStamp) throws Uint64RangeException {
|
||||
MobileCoinLedger.Block.Builder builder = MobileCoinLedger.Block.newBuilder();
|
||||
builder.setBlockNumber(Uint64Util.bigIntegerToUInt64(blockIndex.toBigInteger()));
|
||||
MobileCoinLedger.Block.Builder builder = new MobileCoinLedger.Block.Builder();
|
||||
builder.blockNumber(Uint64Util.bigIntegerToUInt64(blockIndex.toBigInteger()));
|
||||
if (timeStamp != null) {
|
||||
builder.setTimestamp(timeStamp.getTime());
|
||||
builder.timestamp(timeStamp.getTime());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import androidx.annotation.WorkerThread;
|
||||
import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.ComparatorCompat;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.signal.core.util.MapUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
@@ -32,6 +31,8 @@ import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public final class LedgerReconcile {
|
||||
|
||||
private static final String TAG = Log.tag(LedgerReconcile.class);
|
||||
@@ -53,14 +54,14 @@ public final class LedgerReconcile {
|
||||
@NonNull List<MobileCoinLedgerWrapper.OwnedTxo> allTxOuts)
|
||||
{
|
||||
List<? extends Payment> nonFailedLocalPayments = Stream.of(allLocalPaymentTransactions).filter(i -> i.getState() != State.FAILED).toList();
|
||||
Set<ByteString> allKnownPublicKeys = new HashSet<>(nonFailedLocalPayments.size());
|
||||
Set<ByteString> allKnownKeyImages = new HashSet<>(nonFailedLocalPayments.size());
|
||||
Set<ByteString> allKnownPublicKeys = new HashSet<>(nonFailedLocalPayments.size());
|
||||
Set<ByteString> allKnownKeyImages = new HashSet<>(nonFailedLocalPayments.size());
|
||||
|
||||
for (Payment paymentTransaction : nonFailedLocalPayments) {
|
||||
PaymentMetaData.MobileCoinTxoIdentification txoIdentification = paymentTransaction.getPaymentMetaData().getMobileCoinTxoIdentification();
|
||||
PaymentMetaData.MobileCoinTxoIdentification txoIdentification = paymentTransaction.getPaymentMetaData().mobileCoinTxoIdentification;
|
||||
|
||||
allKnownPublicKeys.addAll(txoIdentification.getPublicKeyList());
|
||||
allKnownKeyImages.addAll(txoIdentification.getKeyImagesList());
|
||||
allKnownPublicKeys.addAll(txoIdentification.publicKey);
|
||||
allKnownKeyImages.addAll(txoIdentification.keyImages);
|
||||
}
|
||||
|
||||
Set<MobileCoinLedgerWrapper.OwnedTxo> knownTxosByKeyImage = Stream.of(allTxOuts)
|
||||
@@ -120,7 +121,7 @@ public final class LedgerReconcile {
|
||||
|
||||
private static @NonNull Payment findBlock(@NonNull Payment local, @NonNull Map<ByteString, MobileCoinLedgerWrapper.OwnedTxo> allTxOuts) {
|
||||
if (local.getDirection().isReceived()) {
|
||||
for (ByteString publicKey : local.getPaymentMetaData().getMobileCoinTxoIdentification().getPublicKeyList()) {
|
||||
for (ByteString publicKey : local.getPaymentMetaData().mobileCoinTxoIdentification.publicKey) {
|
||||
MobileCoinLedgerWrapper.OwnedTxo ownedTxo = allTxOuts.get(publicKey);
|
||||
|
||||
if (ownedTxo != null) {
|
||||
@@ -131,7 +132,7 @@ public final class LedgerReconcile {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ByteString keyImage : local.getPaymentMetaData().getMobileCoinTxoIdentification().getKeyImagesList()) {
|
||||
for (ByteString keyImage : local.getPaymentMetaData().mobileCoinTxoIdentification.keyImages) {
|
||||
MobileCoinLedgerWrapper.OwnedTxo ownedTxo = allTxOuts.get(keyImage);
|
||||
|
||||
if (ownedTxo != null && ownedTxo.getSpentInBlock() != null) {
|
||||
|
||||
Reference in New Issue
Block a user