导航菜单

页面标题

页面副标题

imToken v3.28.8 - WalletProtobufSerializer.java 源代码

正在查看: imToken v3.28.8 应用的 WalletProtobufSerializer.java JAVA 源代码文件

本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。


package org.bitcoinj.wallet;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.TextFormat;
import com.google.protobuf.WireFormat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.PeerAddress;
import org.bitcoinj.core.ScriptException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.crypto.KeyCrypter;
import org.bitcoinj.crypto.KeyCrypterScrypt;
import org.bitcoinj.script.Script;
import org.bitcoinj.signers.LocalTransactionSigner;
import org.bitcoinj.signers.TransactionSigner;
import org.bitcoinj.utils.ExchangeRate;
import org.bitcoinj.utils.Fiat;
import org.bitcoinj.wallet.Protos;
import org.bitcoinj.wallet.UnreadableWalletException;
import org.bitcoinj.wallet.WalletTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WalletProtobufSerializer {
    private static final int WALLET_SIZE_LIMIT = 536870912;
    private final WalletFactory factory;
    private KeyChainFactory keyChainFactory;
    private boolean requireMandatoryExtensions;
    protected Map<ByteString, Transaction> txMap;
    private static final Logger log = LoggerFactory.getLogger(WalletProtobufSerializer.class);
    public static final int CURRENT_WALLET_VERSION = Protos.Wallet.getDefaultInstance().getVersion();

    public interface WalletFactory {
        Wallet create(NetworkParameters networkParameters, KeyChainGroup keyChainGroup);
    }

    public WalletProtobufSerializer() {
        this(new WalletFactory() {
            @Override
            public Wallet create(NetworkParameters networkParameters, KeyChainGroup keyChainGroup) {
                return new Wallet(networkParameters, keyChainGroup);
            }
        });
    }

    public WalletProtobufSerializer(WalletFactory walletFactory) {
        this.requireMandatoryExtensions = true;
        this.txMap = new HashMap();
        this.factory = walletFactory;
        this.keyChainFactory = new DefaultKeyChainFactory();
    }

    public void setKeyChainFactory(KeyChainFactory keyChainFactory) {
        this.keyChainFactory = keyChainFactory;
    }

    public void setRequireMandatoryExtensions(boolean z) {
        this.requireMandatoryExtensions = z;
    }

    public void writeWallet(Wallet wallet, OutputStream outputStream) throws IOException {
        walletToProto(wallet).writeTo(outputStream);
    }

    public String walletToText(Wallet wallet) {
        return TextFormat.printToString(walletToProto(wallet));
    }

    public Protos.Wallet walletToProto(Wallet wallet) {
        Protos.Wallet.Builder newBuilder = Protos.Wallet.newBuilder();
        newBuilder.setNetworkIdentifier(wallet.getNetworkParameters().getId());
        if (wallet.getDescription() != null) {
            newBuilder.setDescription(wallet.getDescription());
        }
        Iterator<WalletTransaction> it = wallet.getWalletTransactions().iterator();
        while (it.hasNext()) {
            newBuilder.addTransaction(makeTxProto(it.next()));
        }
        newBuilder.addAllKey(wallet.serializeKeyChainGroupToProtobuf());
        for (Script script : wallet.getWatchedScripts()) {
            newBuilder.addWatchedScript(Protos.Script.newBuilder().setProgram(ByteString.copyFrom(script.getProgram())).setCreationTimestamp(script.getCreationTimeSeconds() * 1000).m2352build());
        }
        Sha256Hash lastBlockSeenHash = wallet.getLastBlockSeenHash();
        if (lastBlockSeenHash != null) {
            newBuilder.setLastSeenBlockHash(hashToByteString(lastBlockSeenHash));
            newBuilder.setLastSeenBlockHeight(wallet.getLastBlockSeenHeight());
        }
        if (wallet.getLastBlockSeenTimeSecs() > 0) {
            newBuilder.setLastSeenBlockTimeSecs(wallet.getLastBlockSeenTimeSecs());
        }
        KeyCrypter keyCrypter = wallet.getKeyCrypter();
        if (keyCrypter == null) {
            newBuilder.setEncryptionType(Protos.Wallet.EncryptionType.UNENCRYPTED);
        } else {
            newBuilder.setEncryptionType(keyCrypter.getUnderstoodEncryptionType());
            if (keyCrypter instanceof KeyCrypterScrypt) {
                newBuilder.setEncryptionParameters(((KeyCrypterScrypt) keyCrypter).getScryptParameters());
            } else {
                throw new RuntimeException("The wallet has encryption of type '" + keyCrypter.getUnderstoodEncryptionType() + "' but this WalletProtobufSerializer does not know how to persist this.");
            }
        }
        if (wallet.getKeyRotationTime() != null) {
            newBuilder.setKeyRotationTime(wallet.getKeyRotationTime().getTime() / 1000);
        }
        populateExtensions(wallet, newBuilder);
        for (Map.Entry<String, ByteString> entry : wallet.getTags().entrySet()) {
            newBuilder.addTags(Protos.Tag.newBuilder().setTag(entry.getKey()).setData(entry.getValue()));
        }
        for (TransactionSigner transactionSigner : wallet.getTransactionSigners()) {
            if (!(transactionSigner instanceof LocalTransactionSigner)) {
                Protos.TransactionSigner.Builder newBuilder2 = Protos.TransactionSigner.newBuilder();
                newBuilder2.setClassName(transactionSigner.getClass().getName());
                newBuilder2.setData(ByteString.copyFrom(transactionSigner.serialize()));
                newBuilder.addTransactionSigners(newBuilder2);
            }
        }
        newBuilder.setVersion(wallet.getVersion());
        return newBuilder.m2596build();
    }

    private static void populateExtensions(Wallet wallet, Protos.Wallet.Builder builder) {
        for (WalletExtension walletExtension : wallet.getExtensions().values()) {
            Protos.Extension.Builder newBuilder = Protos.Extension.newBuilder();
            newBuilder.setId(walletExtension.getWalletExtensionID());
            newBuilder.setMandatory(walletExtension.isWalletExtensionMandatory());
            newBuilder.setData(ByteString.copyFrom(walletExtension.serializeWalletExtension()));
            builder.addExtension(newBuilder);
        }
    }

    private static Protos.Transaction makeTxProto(WalletTransaction walletTransaction) {
        Protos.Transaction.Purpose purpose;
        Transaction transaction = walletTransaction.getTransaction();
        Protos.Transaction.Builder newBuilder = Protos.Transaction.newBuilder();
        newBuilder.setPool(getProtoPool(walletTransaction)).setHash(hashToByteString(transaction.getHash())).setVersion((int) transaction.getVersion());
        if (transaction.getUpdateTime() != null) {
            newBuilder.setUpdatedAt(transaction.getUpdateTime().getTime());
        }
        if (transaction.getLockTime() > 0) {
            newBuilder.setLockTime((int) transaction.getLockTime());
        }
        for (TransactionInput transactionInput : transaction.getInputs()) {
            Protos.TransactionInput.Builder transactionOutPointIndex = Protos.TransactionInput.newBuilder().setScriptBytes(ByteString.copyFrom(transactionInput.getScriptBytes())).setTransactionOutPointHash(hashToByteString(transactionInput.getOutpoint().getHash())).setTransactionOutPointIndex((int) transactionInput.getOutpoint().getIndex());
            if (transactionInput.hasSequence()) {
                transactionOutPointIndex.setSequence((int) transactionInput.getSequenceNumber());
            }
            if (transactionInput.getValue() != null) {
                transactionOutPointIndex.setValue(transactionInput.getValue().value);
            }
            newBuilder.addTransactionInput(transactionOutPointIndex);
        }
        for (TransactionOutput transactionOutput : transaction.getOutputs()) {
            Protos.TransactionOutput.Builder value = Protos.TransactionOutput.newBuilder().setScriptBytes(ByteString.copyFrom(transactionOutput.getScriptBytes())).setValue(transactionOutput.getValue().value);
            TransactionInput spentBy = transactionOutput.getSpentBy();
            if (spentBy != null) {
                Sha256Hash hash = spentBy.getParentTransaction().getHash();
                value.setSpentByTransactionHash(hashToByteString(hash)).setSpentByTransactionIndex(spentBy.getParentTransaction().getInputs().indexOf(spentBy));
            }
            newBuilder.addTransactionOutput(value);
        }
        Map<Sha256Hash, Integer> appearsInHashes = transaction.getAppearsInHashes();
        if (appearsInHashes != null) {
            for (Map.Entry<Sha256Hash, Integer> entry : appearsInHashes.entrySet()) {
                newBuilder.addBlockHash(hashToByteString(entry.getKey()));
                newBuilder.addBlockRelativityOffsets(entry.getValue().intValue());
            }
        }
        if (transaction.hasConfidence()) {
            writeConfidence(newBuilder, transaction.getConfidence(), Protos.TransactionConfidence.newBuilder());
        }
        switch (AnonymousClass2.$SwitchMap$org$bitcoinj$core$Transaction$Purpose[transaction.getPurpose().ordinal()]) {
            case 1:
                purpose = Protos.Transaction.Purpose.UNKNOWN;
                break;
            case 2:
                purpose = Protos.Transaction.Purpose.USER_PAYMENT;
                break;
            case 3:
                purpose = Protos.Transaction.Purpose.KEY_ROTATION;
                break;
            case 4:
                purpose = Protos.Transaction.Purpose.ASSURANCE_CONTRACT_CLAIM;
                break;
            case 5:
                purpose = Protos.Transaction.Purpose.ASSURANCE_CONTRACT_PLEDGE;
                break;
            case 6:
                purpose = Protos.Transaction.Purpose.ASSURANCE_CONTRACT_STUB;
                break;
            case 7:
                purpose = Protos.Transaction.Purpose.RAISE_FEE;
                break;
            default:
                throw new RuntimeException("New tx purpose serialization not implemented.");
        }
        newBuilder.setPurpose(purpose);
        ExchangeRate exchangeRate = transaction.getExchangeRate();
        if (exchangeRate != null) {
            newBuilder.setExchangeRate(Protos.ExchangeRate.newBuilder().setCoinValue(exchangeRate.coin.value).setFiatValue(exchangeRate.fiat.value).setFiatCurrencyCode(exchangeRate.fiat.currencyCode));
        }
        if (transaction.getMemo() != null) {
            newBuilder.setMemo(transaction.getMemo());
        }
        return newBuilder.m2442build();
    }

    private static Protos.Transaction.Pool getProtoPool(WalletTransaction walletTransaction) {
        int i = AnonymousClass2.$SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool[walletTransaction.getPool().ordinal()];
        if (i == 1) {
            return Protos.Transaction.Pool.UNSPENT;
        }
        if (i == 2) {
            return Protos.Transaction.Pool.SPENT;
        }
        if (i == 3) {
            return Protos.Transaction.Pool.DEAD;
        }
        if (i == 4) {
            return Protos.Transaction.Pool.PENDING;
        }
        throw new RuntimeException("Unreachable");
    }

    private static void writeConfidence(Protos.Transaction.Builder builder, TransactionConfidence transactionConfidence, Protos.TransactionConfidence.Builder builder2) {
        synchronized (transactionConfidence) {
            builder2.setType(Protos.TransactionConfidence.Type.valueOf(transactionConfidence.getConfidenceType().getValue()));
            if (transactionConfidence.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
                builder2.setAppearedAtHeight(transactionConfidence.getAppearedAtChainHeight());
                builder2.setDepth(transactionConfidence.getDepthInBlocks());
            }
            if (transactionConfidence.getConfidenceType() == TransactionConfidence.ConfidenceType.DEAD && transactionConfidence.getOverridingTransaction() != null) {
                builder2.setOverridingTransaction(hashToByteString(transactionConfidence.getOverridingTransaction().getHash()));
            }
            int i = AnonymousClass2.$SwitchMap$org$bitcoinj$core$TransactionConfidence$Source[transactionConfidence.getSource().ordinal()];
            if (i == 1) {
                builder2.setSource(Protos.TransactionConfidence.Source.SOURCE_SELF);
            } else if (i == 2) {
                builder2.setSource(Protos.TransactionConfidence.Source.SOURCE_NETWORK);
            } else {
                builder2.setSource(Protos.TransactionConfidence.Source.SOURCE_UNKNOWN);
            }
        }
        for (PeerAddress peerAddress : transactionConfidence.getBroadcastBy()) {
            builder2.addBroadcastBy(Protos.PeerAddress.newBuilder().setIpAddress(ByteString.copyFrom(peerAddress.getAddr().getAddress())).setPort(peerAddress.getPort()).setServices(peerAddress.getServices().longValue()).m2322build());
        }
        Date lastBroadcastedAt = transactionConfidence.getLastBroadcastedAt();
        if (lastBroadcastedAt != null) {
            builder2.setLastBroadcastedAt(lastBroadcastedAt.getTime());
        }
        builder.setConfidence(builder2);
    }

    public static ByteString hashToByteString(Sha256Hash sha256Hash) {
        return ByteString.copyFrom(sha256Hash.getBytes());
    }

    public static Sha256Hash byteStringToHash(ByteString byteString) {
        return Sha256Hash.wrap(byteString.toByteArray());
    }

    public Wallet readWallet(InputStream inputStream, @Nullable WalletExtension... walletExtensionArr) throws UnreadableWalletException {
        return readWallet(inputStream, false, walletExtensionArr);
    }

    public Wallet readWallet(InputStream inputStream, boolean z, @Nullable WalletExtension[] walletExtensionArr) throws UnreadableWalletException {
        try {
            Protos.Wallet parseToProto = parseToProto(inputStream);
            String networkIdentifier = parseToProto.getNetworkIdentifier();
            NetworkParameters fromID = NetworkParameters.fromID(networkIdentifier);
            if (fromID == null) {
                throw new UnreadableWalletException("Unknown network parameters ID " + networkIdentifier);
            }
            return readWallet(fromID, walletExtensionArr, parseToProto, z);
        } catch (IOException e) {
            throw new UnreadableWalletException("Could not parse input stream to protobuf", e);
        } catch (IllegalArgumentException e2) {
            throw new UnreadableWalletException("Could not parse input stream to protobuf", e2);
        } catch (IllegalStateException e3) {
            throw new UnreadableWalletException("Could not parse input stream to protobuf", e3);
        }
    }

    public Wallet readWallet(NetworkParameters networkParameters, @Nullable WalletExtension[] walletExtensionArr, Protos.Wallet wallet) throws UnreadableWalletException {
        return readWallet(networkParameters, walletExtensionArr, wallet, false);
    }

    public Wallet readWallet(NetworkParameters networkParameters, @Nullable WalletExtension[] walletExtensionArr, Protos.Wallet wallet, boolean z) throws UnreadableWalletException {
        KeyChainGroup fromProtobufUnencrypted;
        if (wallet.getVersion() > CURRENT_WALLET_VERSION) {
            throw new UnreadableWalletException.FutureVersion();
        }
        if (!wallet.getNetworkIdentifier().equals(networkParameters.getId())) {
            throw new UnreadableWalletException.WrongNetwork();
        }
        if (wallet.hasEncryptionParameters()) {
            fromProtobufUnencrypted = KeyChainGroup.fromProtobufEncrypted(networkParameters, wallet.getKeyList(), new KeyCrypterScrypt(wallet.getEncryptionParameters()), this.keyChainFactory);
        } else {
            fromProtobufUnencrypted = KeyChainGroup.fromProtobufUnencrypted(networkParameters, wallet.getKeyList(), this.keyChainFactory);
        }
        Wallet create = this.factory.create(networkParameters, fromProtobufUnencrypted);
        ArrayList newArrayList = Lists.newArrayList();
        for (Protos.Script script : wallet.getWatchedScriptList()) {
            try {
                newArrayList.add(new Script(script.getProgram().toByteArray(), script.getCreationTimestamp() / 1000));
            } catch (ScriptException unused) {
                throw new UnreadableWalletException("Unparseable script in wallet");
            }
        }
        create.addWatchedScripts(newArrayList);
        if (wallet.hasDescription()) {
            create.setDescription(wallet.getDescription());
        }
        if (z) {
            create.setLastBlockSeenHash(null);
            create.setLastBlockSeenHeight(-1);
            create.setLastBlockSeenTimeSecs(0L);
        } else {
            Iterator<Protos.Transaction> it = wallet.getTransactionList().iterator();
            while (it.hasNext()) {
                readTransaction(it.next(), create.getParams());
            }
            Iterator<Protos.Transaction> it2 = wallet.getTransactionList().iterator();
            while (it2.hasNext()) {
                create.addWalletTransaction(connectTransactionOutputs(networkParameters, it2.next()));
            }
            if (!wallet.hasLastSeenBlockHash()) {
                create.setLastBlockSeenHash(null);
            } else {
                create.setLastBlockSeenHash(byteStringToHash(wallet.getLastSeenBlockHash()));
            }
            if (!wallet.hasLastSeenBlockHeight()) {
                create.setLastBlockSeenHeight(-1);
            } else {
                create.setLastBlockSeenHeight(wallet.getLastSeenBlockHeight());
            }
            create.setLastBlockSeenTimeSecs(wallet.getLastSeenBlockTimeSecs());
            if (wallet.hasKeyRotationTime()) {
                create.setKeyRotationTime(new Date(wallet.getKeyRotationTime() * 1000));
            }
        }
        if (walletExtensionArr == null) {
            walletExtensionArr = new WalletExtension[0];
        }
        loadExtensions(create, walletExtensionArr, wallet);
        for (Protos.Tag tag : wallet.getTagsList()) {
            create.setTag(tag.getTag(), tag.getData());
        }
        for (Protos.TransactionSigner transactionSigner : wallet.getTransactionSignersList()) {
            try {
                TransactionSigner transactionSigner2 = (TransactionSigner) Class.forName(transactionSigner.getClassName()).newInstance();
                transactionSigner2.deserialize(transactionSigner.getData().toByteArray());
                create.addTransactionSigner(transactionSigner2);
            } catch (Exception e) {
                throw new UnreadableWalletException("Unable to deserialize TransactionSigner instance: " + transactionSigner.getClassName(), e);
            }
        }
        if (wallet.hasVersion()) {
            create.setVersion(wallet.getVersion());
        }
        this.txMap.clear();
        return create;
    }

    private void loadExtensions(Wallet wallet, WalletExtension[] walletExtensionArr, Protos.Wallet wallet2) throws UnreadableWalletException {
        HashMap hashMap = new HashMap();
        for (WalletExtension walletExtension : walletExtensionArr) {
            hashMap.put(walletExtension.getWalletExtensionID(), walletExtension);
        }
        hashMap.putAll(wallet.getExtensions());
        for (Protos.Extension extension : wallet2.getExtensionList()) {
            String id = extension.getId();
            WalletExtension walletExtension2 = (WalletExtension) hashMap.get(id);
            if (walletExtension2 == null) {
                if (!extension.getMandatory()) {
                    continue;
                } else {
                    if (this.requireMandatoryExtensions) {
                        throw new UnreadableWalletException("Unknown mandatory extension in wallet: " + id);
                    }
                    log.error("Unknown extension in wallet {}, ignoring", id);
                }
            } else {
                log.info("Loading wallet extension {}", id);
                try {
                    wallet.deserializeExtension(walletExtension2, extension.getData().toByteArray());
                } catch (Exception unused) {
                    if (!extension.getMandatory()) {
                        continue;
                    } else if (this.requireMandatoryExtensions) {
                        log.error("Error whilst reading mandatory extension {}, failing to read wallet", id);
                        throw new UnreadableWalletException("Could not parse mandatory extension in wallet: " + id);
                    }
                }
            }
        }
    }

    public static Protos.Wallet parseToProto(InputStream inputStream) throws IOException {
        CodedInputStream newInstance = CodedInputStream.newInstance(inputStream);
        newInstance.setSizeLimit(WALLET_SIZE_LIMIT);
        return Protos.Wallet.parseFrom(newInstance);
    }

    private void readTransaction(Protos.Transaction transaction, NetworkParameters networkParameters) throws UnreadableWalletException {
        Transaction transaction2 = new Transaction(networkParameters);
        transaction2.setVersion(transaction.getVersion());
        if (transaction.hasUpdatedAt()) {
            transaction2.setUpdateTime(new Date(transaction.getUpdatedAt()));
        }
        for (Protos.TransactionOutput transactionOutput : transaction.getTransactionOutputList()) {
            transaction2.addOutput(new TransactionOutput(networkParameters, transaction2, Coin.valueOf(transactionOutput.getValue()), transactionOutput.getScriptBytes().toByteArray()));
        }
        for (Protos.TransactionInput transactionInput : transaction.getTransactionInputList()) {
            TransactionInput transactionInput2 = new TransactionInput(networkParameters, transaction2, transactionInput.getScriptBytes().toByteArray(), new TransactionOutPoint(networkParameters, transactionInput.getTransactionOutPointIndex() & TransactionInput.NO_SEQUENCE, byteStringToHash(transactionInput.getTransactionOutPointHash())), transactionInput.hasValue() ? Coin.valueOf(transactionInput.getValue()) : null);
            if (transactionInput.hasSequence()) {
                transactionInput2.setSequenceNumber(transactionInput.getSequence() & TransactionInput.NO_SEQUENCE);
            }
            transaction2.addInput(transactionInput2);
        }
        for (int i = 0; i < transaction.getBlockHashCount(); i++) {
            transaction2.addBlockAppearance(byteStringToHash(transaction.getBlockHash(i)), transaction.getBlockRelativityOffsetsCount() > 0 ? transaction.getBlockRelativityOffsets(i) : 0);
        }
        if (transaction.hasLockTime()) {
            transaction2.setLockTime(transaction.getLockTime() & TransactionInput.NO_SEQUENCE);
        }
        if (transaction.hasPurpose()) {
            switch (AnonymousClass2.$SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[transaction.getPurpose().ordinal()]) {
                case 1:
                    transaction2.setPurpose(Transaction.Purpose.UNKNOWN);
                    break;
                case 2:
                    transaction2.setPurpose(Transaction.Purpose.USER_PAYMENT);
                    break;
                case 3:
                    transaction2.setPurpose(Transaction.Purpose.KEY_ROTATION);
                    break;
                case 4:
                    transaction2.setPurpose(Transaction.Purpose.ASSURANCE_CONTRACT_CLAIM);
                    break;
                case 5:
                    transaction2.setPurpose(Transaction.Purpose.ASSURANCE_CONTRACT_PLEDGE);
                    break;
                case 6:
                    transaction2.setPurpose(Transaction.Purpose.ASSURANCE_CONTRACT_STUB);
                    break;
                case 7:
                    transaction2.setPurpose(Transaction.Purpose.RAISE_FEE);
                    break;
                default:
                    throw new RuntimeException("New purpose serialization not implemented");
            }
        } else {
            transaction2.setPurpose(Transaction.Purpose.USER_PAYMENT);
        }
        if (transaction.hasExchangeRate()) {
            Protos.ExchangeRate exchangeRate = transaction.getExchangeRate();
            transaction2.setExchangeRate(new ExchangeRate(Coin.valueOf(exchangeRate.getCoinValue()), Fiat.valueOf(exchangeRate.getFiatCurrencyCode(), exchangeRate.getFiatValue())));
        }
        if (transaction.hasMemo()) {
            transaction2.setMemo(transaction.getMemo());
        }
        Sha256Hash byteStringToHash = byteStringToHash(transaction.getHash());
        if (!transaction2.getHash().equals(byteStringToHash)) {
            throw new UnreadableWalletException(String.format(Locale.US, "Transaction did not deserialize completely: %s vs %s", transaction2.getHash(), byteStringToHash));
        }
        if (this.txMap.containsKey(transaction.getHash())) {
            throw new UnreadableWalletException("Wallet contained duplicate transaction " + byteStringToHash(transaction.getHash()));
        }
        this.txMap.put(transaction.getHash(), transaction2);
    }

    private WalletTransaction connectTransactionOutputs(NetworkParameters networkParameters, Protos.Transaction transaction) throws UnreadableWalletException {
        WalletTransaction.Pool pool;
        Transaction transaction2 = this.txMap.get(transaction.getHash());
        switch (AnonymousClass2.$SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[transaction.getPool().ordinal()]) {
            case 1:
                pool = WalletTransaction.Pool.DEAD;
                break;
            case 2:
                pool = WalletTransaction.Pool.PENDING;
                break;
            case 3:
                pool = WalletTransaction.Pool.SPENT;
                break;
            case 4:
                pool = WalletTransaction.Pool.UNSPENT;
                break;
            case 5:
            case 6:
                pool = WalletTransaction.Pool.PENDING;
                break;
            default:
                throw new UnreadableWalletException("Unknown transaction pool: " + transaction.getPool());
        }
        for (int i = 0; i < transaction2.getOutputs().size(); i++) {
            TransactionOutput transactionOutput = transaction2.getOutputs().get(i);
            Protos.TransactionOutput transactionOutput2 = transaction.getTransactionOutput(i);
            if (transactionOutput2.hasSpentByTransactionHash()) {
                ByteString spentByTransactionHash = transactionOutput2.getSpentByTransactionHash();
                Transaction transaction3 = this.txMap.get(spentByTransactionHash);
                if (transaction3 == null) {
                    throw new UnreadableWalletException(String.format(Locale.US, "Could not connect %s to %s", transaction2.getHashAsString(), byteStringToHash(spentByTransactionHash)));
                }
                ((TransactionInput) Preconditions.checkNotNull(transaction3.getInput(transactionOutput2.getSpentByTransactionIndex()))).connect(transactionOutput);
            }
        }
        if (transaction.hasConfidence()) {
            readConfidence(networkParameters, transaction2, transaction.getConfidence(), transaction2.getConfidence());
        }
        return new WalletTransaction(pool, transaction2);
    }

    private void readConfidence(NetworkParameters networkParameters, Transaction transaction, Protos.TransactionConfidence transactionConfidence, TransactionConfidence transactionConfidence2) throws UnreadableWalletException {
        TransactionConfidence.ConfidenceType confidenceType;
        if (!transactionConfidence.hasType()) {
            log.warn("Unknown confidence type for tx {}", transaction.getHashAsString());
            return;
        }
        int i = AnonymousClass2.$SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[transactionConfidence.getType().ordinal()];
        if (i == 1) {
            confidenceType = TransactionConfidence.ConfidenceType.BUILDING;
        } else if (i == 2) {
            confidenceType = TransactionConfidence.ConfidenceType.DEAD;
        } else if (i == 3) {
            confidenceType = TransactionConfidence.ConfidenceType.PENDING;
        } else if (i == 4) {
            confidenceType = TransactionConfidence.ConfidenceType.PENDING;
        } else if (i == 5) {
            confidenceType = TransactionConfidence.ConfidenceType.IN_CONFLICT;
        } else {
            confidenceType = TransactionConfidence.ConfidenceType.UNKNOWN;
        }
        transactionConfidence2.setConfidenceType(confidenceType);
        if (transactionConfidence.hasAppearedAtHeight()) {
            if (transactionConfidence2.getConfidenceType() != TransactionConfidence.ConfidenceType.BUILDING) {
                log.warn("Have appearedAtHeight but not BUILDING for tx {}", transaction.getHashAsString());
                return;
            }
            transactionConfidence2.setAppearedAtChainHeight(transactionConfidence.getAppearedAtHeight());
        }
        if (transactionConfidence.hasDepth()) {
            if (transactionConfidence2.getConfidenceType() != TransactionConfidence.ConfidenceType.BUILDING) {
                log.warn("Have depth but not BUILDING for tx {}", transaction.getHashAsString());
                return;
            }
            transactionConfidence2.setDepthInBlocks(transactionConfidence.getDepth());
        }
        if (transactionConfidence.hasOverridingTransaction()) {
            if (transactionConfidence2.getConfidenceType() != TransactionConfidence.ConfidenceType.DEAD) {
                log.warn("Have overridingTransaction but not OVERRIDDEN for tx {}", transaction.getHashAsString());
                return;
            }
            Transaction transaction2 = this.txMap.get(transactionConfidence.getOverridingTransaction());
            if (transaction2 == null) {
                log.warn("Have overridingTransaction that is not in wallet for tx {}", transaction.getHashAsString());
                return;
            }
            transactionConfidence2.setOverridingTransaction(transaction2);
        }
        for (Protos.PeerAddress peerAddress : transactionConfidence.getBroadcastByList()) {
            try {
                PeerAddress peerAddress2 = new PeerAddress(networkParameters, InetAddress.getByAddress(peerAddress.getIpAddress().toByteArray()), peerAddress.getPort());
                peerAddress2.setServices(BigInteger.valueOf(peerAddress.getServices()));
                transactionConfidence2.markBroadcastBy(peerAddress2);
            } catch (UnknownHostException e) {
                throw new UnreadableWalletException("Peer IP address does not have the right length", e);
            }
        }
        if (transactionConfidence.hasLastBroadcastedAt()) {
            transactionConfidence2.setLastBroadcastedAt(new Date(transactionConfidence.getLastBroadcastedAt()));
        }
        int i2 = AnonymousClass2.$SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Source[transactionConfidence.getSource().ordinal()];
        if (i2 == 1) {
            transactionConfidence2.setSource(TransactionConfidence.Source.SELF);
        } else if (i2 == 2) {
            transactionConfidence2.setSource(TransactionConfidence.Source.NETWORK);
        } else {
            transactionConfidence2.setSource(TransactionConfidence.Source.UNKNOWN);
        }
    }

    static class AnonymousClass2 {
        static final int[] $SwitchMap$org$bitcoinj$core$Transaction$Purpose;
        static final int[] $SwitchMap$org$bitcoinj$core$TransactionConfidence$Source;
        static final int[] $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool;
        static final int[] $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose;
        static final int[] $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Source;
        static final int[] $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type;
        static final int[] $SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool;

        static {
            int[] iArr = new int[Protos.TransactionConfidence.Source.values().length];
            $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Source = iArr;
            try {
                iArr[Protos.TransactionConfidence.Source.SOURCE_SELF.ordinal()] = 1;
            } catch (NoSuchFieldError unused) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Source[Protos.TransactionConfidence.Source.SOURCE_NETWORK.ordinal()] = 2;
            } catch (NoSuchFieldError unused2) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Source[Protos.TransactionConfidence.Source.SOURCE_UNKNOWN.ordinal()] = 3;
            } catch (NoSuchFieldError unused3) {
            }
            int[] iArr2 = new int[Protos.TransactionConfidence.Type.values().length];
            $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type = iArr2;
            try {
                iArr2[Protos.TransactionConfidence.Type.BUILDING.ordinal()] = 1;
            } catch (NoSuchFieldError unused4) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[Protos.TransactionConfidence.Type.DEAD.ordinal()] = 2;
            } catch (NoSuchFieldError unused5) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[Protos.TransactionConfidence.Type.NOT_IN_BEST_CHAIN.ordinal()] = 3;
            } catch (NoSuchFieldError unused6) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[Protos.TransactionConfidence.Type.PENDING.ordinal()] = 4;
            } catch (NoSuchFieldError unused7) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[Protos.TransactionConfidence.Type.IN_CONFLICT.ordinal()] = 5;
            } catch (NoSuchFieldError unused8) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$TransactionConfidence$Type[Protos.TransactionConfidence.Type.UNKNOWN.ordinal()] = 6;
            } catch (NoSuchFieldError unused9) {
            }
            int[] iArr3 = new int[Protos.Transaction.Pool.values().length];
            $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool = iArr3;
            try {
                iArr3[Protos.Transaction.Pool.DEAD.ordinal()] = 1;
            } catch (NoSuchFieldError unused10) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[Protos.Transaction.Pool.PENDING.ordinal()] = 2;
            } catch (NoSuchFieldError unused11) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[Protos.Transaction.Pool.SPENT.ordinal()] = 3;
            } catch (NoSuchFieldError unused12) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[Protos.Transaction.Pool.UNSPENT.ordinal()] = 4;
            } catch (NoSuchFieldError unused13) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[Protos.Transaction.Pool.INACTIVE.ordinal()] = 5;
            } catch (NoSuchFieldError unused14) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Pool[Protos.Transaction.Pool.PENDING_INACTIVE.ordinal()] = 6;
            } catch (NoSuchFieldError unused15) {
            }
            int[] iArr4 = new int[Protos.Transaction.Purpose.values().length];
            $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose = iArr4;
            try {
                iArr4[Protos.Transaction.Purpose.UNKNOWN.ordinal()] = 1;
            } catch (NoSuchFieldError unused16) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.USER_PAYMENT.ordinal()] = 2;
            } catch (NoSuchFieldError unused17) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.KEY_ROTATION.ordinal()] = 3;
            } catch (NoSuchFieldError unused18) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.ASSURANCE_CONTRACT_CLAIM.ordinal()] = 4;
            } catch (NoSuchFieldError unused19) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.ASSURANCE_CONTRACT_PLEDGE.ordinal()] = 5;
            } catch (NoSuchFieldError unused20) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.ASSURANCE_CONTRACT_STUB.ordinal()] = 6;
            } catch (NoSuchFieldError unused21) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$Protos$Transaction$Purpose[Protos.Transaction.Purpose.RAISE_FEE.ordinal()] = 7;
            } catch (NoSuchFieldError unused22) {
            }
            int[] iArr5 = new int[TransactionConfidence.Source.values().length];
            $SwitchMap$org$bitcoinj$core$TransactionConfidence$Source = iArr5;
            try {
                iArr5[TransactionConfidence.Source.SELF.ordinal()] = 1;
            } catch (NoSuchFieldError unused23) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$TransactionConfidence$Source[TransactionConfidence.Source.NETWORK.ordinal()] = 2;
            } catch (NoSuchFieldError unused24) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$TransactionConfidence$Source[TransactionConfidence.Source.UNKNOWN.ordinal()] = 3;
            } catch (NoSuchFieldError unused25) {
            }
            int[] iArr6 = new int[WalletTransaction.Pool.values().length];
            $SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool = iArr6;
            try {
                iArr6[WalletTransaction.Pool.UNSPENT.ordinal()] = 1;
            } catch (NoSuchFieldError unused26) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool[WalletTransaction.Pool.SPENT.ordinal()] = 2;
            } catch (NoSuchFieldError unused27) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool[WalletTransaction.Pool.DEAD.ordinal()] = 3;
            } catch (NoSuchFieldError unused28) {
            }
            try {
                $SwitchMap$org$bitcoinj$wallet$WalletTransaction$Pool[WalletTransaction.Pool.PENDING.ordinal()] = 4;
            } catch (NoSuchFieldError unused29) {
            }
            int[] iArr7 = new int[Transaction.Purpose.values().length];
            $SwitchMap$org$bitcoinj$core$Transaction$Purpose = iArr7;
            try {
                iArr7[Transaction.Purpose.UNKNOWN.ordinal()] = 1;
            } catch (NoSuchFieldError unused30) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.USER_PAYMENT.ordinal()] = 2;
            } catch (NoSuchFieldError unused31) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.KEY_ROTATION.ordinal()] = 3;
            } catch (NoSuchFieldError unused32) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.ASSURANCE_CONTRACT_CLAIM.ordinal()] = 4;
            } catch (NoSuchFieldError unused33) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.ASSURANCE_CONTRACT_PLEDGE.ordinal()] = 5;
            } catch (NoSuchFieldError unused34) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.ASSURANCE_CONTRACT_STUB.ordinal()] = 6;
            } catch (NoSuchFieldError unused35) {
            }
            try {
                $SwitchMap$org$bitcoinj$core$Transaction$Purpose[Transaction.Purpose.RAISE_FEE.ordinal()] = 7;
            } catch (NoSuchFieldError unused36) {
            }
        }
    }

    public static boolean isWallet(InputStream inputStream) {
        try {
            CodedInputStream newInstance = CodedInputStream.newInstance(inputStream);
            if (WireFormat.getTagFieldNumber(newInstance.readTag()) != 1) {
                return false;
            }
            return NetworkParameters.fromID(newInstance.readString()) != null;
        } catch (IOException unused) {
            return false;
        }
    }
}