mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-24 22:58:32 +01:00
Be lenient in parsing tx confidence protobuf, store pubkeys, cleanup
This commit is contained in:
parent
1c28bd3972
commit
69ee4c7729
9 changed files with 350 additions and 208 deletions
|
@ -26,14 +26,24 @@ package wallet;
|
||||||
option java_package = "org.bitcoinj.wallet";
|
option java_package = "org.bitcoinj.wallet";
|
||||||
option java_outer_classname = "Protos";
|
option java_outer_classname = "Protos";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key use to control Bitcoin spending
|
||||||
|
*
|
||||||
|
* Either the private key, the public key or both may be present. It is recommended that
|
||||||
|
* if the private key is provided that the public key is provided too because deriving it is slow.
|
||||||
|
*
|
||||||
|
* If only the public key is provided, the key can only be used to watch the blockchain and verify
|
||||||
|
* transactions, and not for spending.
|
||||||
|
*/
|
||||||
message Key {
|
message Key {
|
||||||
enum Type {
|
enum Type {
|
||||||
ORIGINAL = 1; // Original bitcoin secp256k1 curve
|
ORIGINAL = 1; // Original bitcoin secp256k1 curve
|
||||||
}
|
}
|
||||||
required bytes private_key = 1; // integer representation of the EC private key
|
required Type type = 1;
|
||||||
required Type type = 2;
|
optional bytes private_key = 2; // integer representation of the EC private key
|
||||||
optional string label = 3; // for presentation purposes
|
optional bytes public_key = 3; // integer representation of the EC public key
|
||||||
optional int64 creation_timestamp = 4; // datetime stored as millis since epoch.
|
optional string label = 4; // for presentation purposes
|
||||||
|
optional int64 creation_timestamp = 5; // datetime stored as millis since epoch.
|
||||||
}
|
}
|
||||||
|
|
||||||
message TransactionInput {
|
message TransactionInput {
|
||||||
|
@ -53,20 +63,30 @@ message TransactionOutput {
|
||||||
// if spent, the index of the transaction output of the transaction doing the spend
|
// if spent, the index of the transaction output of the transaction doing the spend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of the confidence we have that a transaction cannot be reversed in the future.
|
||||||
|
*
|
||||||
|
* Parsing should be lenient, since this could change for different applications yet we should
|
||||||
|
* maintain backward compatibility.
|
||||||
|
*/
|
||||||
|
|
||||||
message TransactionConfidence {
|
message TransactionConfidence {
|
||||||
enum Type {
|
enum Type {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
BUILDING = 1;
|
BUILDING = 1; // In best chain. If and only if appeared_at_height is present.
|
||||||
NOT_SEEN_IN_CHAIN = 2;
|
NOT_SEEN_IN_CHAIN = 2; // Pending inclusion in best chain.
|
||||||
NOT_IN_BEST_CHAIN = 3;
|
NOT_IN_BEST_CHAIN = 3; // In non-best chain, pending inclusion in best chain.
|
||||||
OVERRIDDEN_BY_DOUBLE_SPEND = 4;
|
OVERRIDDEN_BY_DOUBLE_SPEND = 4; // If and only if overriding_transaction is present.
|
||||||
}
|
}
|
||||||
|
|
||||||
required Type type = 1;
|
// This is optional in case we add confidence types to prevent parse errors - backwards compatible.
|
||||||
|
optional Type type = 1;
|
||||||
optional int32 appeared_at_height = 2;
|
optional int32 appeared_at_height = 2;
|
||||||
optional bytes overriding_transaction = 3;
|
optional bytes overriding_transaction = 3; // Hash of tx. Should be in this wallet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bitcoin transaction */
|
||||||
|
|
||||||
message Transaction {
|
message Transaction {
|
||||||
/**
|
/**
|
||||||
* This is a bitfield oriented enum, with the following bits:
|
* This is a bitfield oriented enum, with the following bits:
|
||||||
|
@ -107,6 +127,7 @@ message Transaction {
|
||||||
// Sha256Hash of block in block chain in which this transaction appears
|
// Sha256Hash of block in block chain in which this transaction appears
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** An extension to the wallet */
|
||||||
message Extension {
|
message Extension {
|
||||||
required string id = 1; // like org.whatever.foo.bar
|
required string id = 1; // like org.whatever.foo.bar
|
||||||
required bytes data = 2;
|
required bytes data = 2;
|
||||||
|
@ -116,6 +137,7 @@ message Extension {
|
||||||
required bool mandatory = 3;
|
required bool mandatory = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A bitcoin wallet */
|
||||||
message Wallet {
|
message Wallet {
|
||||||
required string network_identifier = 1; // the network used by this wallet
|
required string network_identifier = 1; // the network used by this wallet
|
||||||
// org.bitcoin.production = production network (Satoshi genesis block)
|
// org.bitcoin.production = production network (Satoshi genesis block)
|
||||||
|
|
|
@ -49,6 +49,6 @@ public class DumpedPrivateKey extends VersionedChecksummedBytes {
|
||||||
* Returns an ECKey created from this encoded private key.
|
* Returns an ECKey created from this encoded private key.
|
||||||
*/
|
*/
|
||||||
public ECKey getKey() {
|
public ECKey getKey() {
|
||||||
return new ECKey(new BigInteger(1, bytes), null);
|
return new ECKey(new BigInteger(1, bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class ECKey implements Serializable {
|
||||||
* reference implementation in its wallet. Note that this is slow because it requires an EC point multiply.
|
* reference implementation in its wallet. Note that this is slow because it requires an EC point multiply.
|
||||||
*/
|
*/
|
||||||
public static ECKey fromASN1(byte[] asn1privkey) {
|
public static ECKey fromASN1(byte[] asn1privkey) {
|
||||||
return new ECKey(extractPrivateKeyFromASN1(asn1privkey), null);
|
return new ECKey(extractPrivateKeyFromASN1(asn1privkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,7 +122,7 @@ public class ECKey implements Serializable {
|
||||||
* the public key already correctly matches the public key. If only the public key is supplied, this ECKey cannot
|
* the public key already correctly matches the public key. If only the public key is supplied, this ECKey cannot
|
||||||
* be used for signing.
|
* be used for signing.
|
||||||
*/
|
*/
|
||||||
public ECKey(BigInteger privKey, BigInteger pubKey) {
|
private ECKey(BigInteger privKey, byte[] pubKey) {
|
||||||
this.priv = privKey;
|
this.priv = privKey;
|
||||||
this.pub = null;
|
this.pub = null;
|
||||||
if (pubKey == null && privKey != null) {
|
if (pubKey == null && privKey != null) {
|
||||||
|
@ -132,22 +132,27 @@ public class ECKey implements Serializable {
|
||||||
// We expect the pubkey to be in regular encoded form, just as a BigInteger. Therefore the first byte is
|
// We expect the pubkey to be in regular encoded form, just as a BigInteger. Therefore the first byte is
|
||||||
// a special marker byte.
|
// a special marker byte.
|
||||||
// TODO: This is probably not a useful API and may be confusing.
|
// TODO: This is probably not a useful API and may be confusing.
|
||||||
this.pub = Utils.bigIntegerToBytes(pubKey, 65);
|
this.pub = pubKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates an ECKey given the private key only. The public key is calculated from it (this is slow) */
|
||||||
|
public ECKey(BigInteger privKey) {
|
||||||
|
this(privKey, (byte[])null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A constructor variant with BigInteger pubkey. See {@link ECKey#ECKey(BigInteger, byte[])}. */
|
||||||
|
public ECKey(BigInteger privKey, BigInteger pubKey) {
|
||||||
|
this(privKey, Utils.bigIntegerToBytes(pubKey, 65));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an ECKey given only the private key bytes. This is the same as using the BigInteger constructor, but
|
* Creates an ECKey given only the private key bytes. This is the same as using the BigInteger constructor, but
|
||||||
* is more convenient if you are importing a key from elsewhere. The public key will be automatically derived
|
* is more convenient if you are importing a key from elsewhere. The public key will be automatically derived
|
||||||
* from the private key. Same as calling {@link ECKey#fromPrivKeyBytes(byte[])}.
|
* from the private key. Same as calling {@link ECKey#fromPrivKeyBytes(byte[])}.
|
||||||
*/
|
*/
|
||||||
public ECKey(byte[] privKeyBytes, byte[] pubKeyBytes) {
|
public ECKey(byte[] privKeyBytes, byte[] pubKey) {
|
||||||
priv = privKeyBytes == null ? null : new BigInteger(1, privKeyBytes);
|
this(privKeyBytes == null ? null : new BigInteger(1, privKeyBytes), pubKey);
|
||||||
pub = pubKeyBytes;
|
|
||||||
if (pub == null && priv != null) {
|
|
||||||
// Derive public from private.
|
|
||||||
pub = publicKeyFromPrivate(priv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,10 +289,6 @@ public class ECKey implements Serializable {
|
||||||
return Utils.bigIntegerToBytes(priv, 32);
|
return Utils.bigIntegerToBytes(priv, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ECKey fromPrivKeyBytes(byte[] bytes) {
|
|
||||||
return new ECKey(new BigInteger(1, bytes), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exports the private key in the form used by the Satoshi client "dumpprivkey" and "importprivkey" commands. Use
|
* Exports the private key in the form used by the Satoshi client "dumpprivkey" and "importprivkey" commands. Use
|
||||||
* the {@link com.google.bitcoin.core.DumpedPrivateKey#toString()} method to get the string.
|
* the {@link com.google.bitcoin.core.DumpedPrivateKey#toString()} method to get the string.
|
||||||
|
|
|
@ -707,7 +707,7 @@ public class Transaction extends ChildMessage implements Serializable {
|
||||||
return confidence;
|
return confidence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check if the transaction has a known confidence */
|
||||||
public boolean hasConfidence() {
|
public boolean hasConfidence() {
|
||||||
return confidence != null && confidence.getConfidenceType() != TransactionConfidence.ConfidenceType.UNKNOWN;
|
return confidence != null && confidence.getConfidenceType() != TransactionConfidence.ConfidenceType.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,9 @@ public class Utils {
|
||||||
* @return 32 byte long array.
|
* @return 32 byte long array.
|
||||||
*/
|
*/
|
||||||
public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
|
public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
|
||||||
|
if (b == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
byte[] bytes = new byte[numBytes];
|
byte[] bytes = new byte[numBytes];
|
||||||
byte[] biBytes = b.toByteArray();
|
byte[] biBytes = b.toByteArray();
|
||||||
int start = (biBytes.length == numBytes + 1) ? 1 : 0;
|
int start = (biBytes.length == numBytes + 1) ? 1 : 0;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class PrivateKeys {
|
||||||
key = dumpedPrivateKey.getKey();
|
key = dumpedPrivateKey.getKey();
|
||||||
} else {
|
} else {
|
||||||
BigInteger privKey = Base58.decodeToBigInteger(args[0]);
|
BigInteger privKey = Base58.decodeToBigInteger(args[0]);
|
||||||
key = new ECKey(privKey, null);
|
key = new ECKey(privKey);
|
||||||
}
|
}
|
||||||
System.out.println("Address from private key is: " + key.toAddress(params).toString());
|
System.out.println("Address from private key is: " + key.toAddress(params).toString());
|
||||||
// And the address ...
|
// And the address ...
|
||||||
|
|
|
@ -31,6 +31,8 @@ import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.TextFormat;
|
import com.google.protobuf.TextFormat;
|
||||||
|
|
||||||
import org.bitcoinj.wallet.Protos;
|
import org.bitcoinj.wallet.Protos;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -46,6 +48,8 @@ import java.util.Map;
|
||||||
* @author Miron Cuperman
|
* @author Miron Cuperman
|
||||||
*/
|
*/
|
||||||
public class WalletProtobufSerializer {
|
public class WalletProtobufSerializer {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(WalletProtobufSerializer.class);
|
||||||
|
|
||||||
// Used for de-serialization
|
// Used for de-serialization
|
||||||
private Map<ByteString, Transaction> txMap;
|
private Map<ByteString, Transaction> txMap;
|
||||||
|
|
||||||
|
@ -82,7 +86,9 @@ public class WalletProtobufSerializer {
|
||||||
// .setCreationTimestamp() TODO
|
// .setCreationTimestamp() TODO
|
||||||
// .setLabel() TODO
|
// .setLabel() TODO
|
||||||
.setType(Protos.Key.Type.ORIGINAL)
|
.setType(Protos.Key.Type.ORIGINAL)
|
||||||
.setPrivateKey(ByteString.copyFrom(key.getPrivKeyBytes())));
|
.setPrivateKey(ByteString.copyFrom(key.getPrivKeyBytes()))
|
||||||
|
.setPublicKey(ByteString.copyFrom(key.getPubKey()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return walletBuilder.build();
|
return walletBuilder.build();
|
||||||
}
|
}
|
||||||
|
@ -126,9 +132,11 @@ public class WalletProtobufSerializer {
|
||||||
.setValue(output.getValue().longValue());
|
.setValue(output.getValue().longValue());
|
||||||
final TransactionInput spentBy = output.getSpentBy();
|
final TransactionInput spentBy = output.getSpentBy();
|
||||||
if (spentBy != null) {
|
if (spentBy != null) {
|
||||||
|
Sha256Hash spendingHash = spentBy.getParentTransaction().getHash();
|
||||||
outputBuilder
|
outputBuilder
|
||||||
.setSpentByTransactionHash(ByteString.copyFrom(spentBy.getParentTransaction().getHash().getBytes()))
|
.setSpentByTransactionHash(hashToByteString(spendingHash))
|
||||||
.setSpentByTransactionIndex(spentBy.getParentTransaction().getInputs().indexOf(spentBy));
|
.setSpentByTransactionIndex(
|
||||||
|
spentBy.getParentTransaction().getInputs().indexOf(spentBy));
|
||||||
}
|
}
|
||||||
txBuilder.addTransactionOutput(outputBuilder);
|
txBuilder.addTransactionOutput(outputBuilder);
|
||||||
}
|
}
|
||||||
|
@ -136,7 +144,7 @@ public class WalletProtobufSerializer {
|
||||||
// Handle which blocks tx was seen in
|
// Handle which blocks tx was seen in
|
||||||
if (tx.getAppearsInHashes() != null) {
|
if (tx.getAppearsInHashes() != null) {
|
||||||
for (Sha256Hash hash : tx.getAppearsInHashes()) {
|
for (Sha256Hash hash : tx.getAppearsInHashes()) {
|
||||||
txBuilder.addBlockHash(ByteString.copyFrom(hash.getBytes()));
|
txBuilder.addBlockHash(hashToByteString(hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,20 +153,33 @@ public class WalletProtobufSerializer {
|
||||||
Protos.TransactionConfidence.Builder confidenceBuilder =
|
Protos.TransactionConfidence.Builder confidenceBuilder =
|
||||||
Protos.TransactionConfidence.newBuilder();
|
Protos.TransactionConfidence.newBuilder();
|
||||||
|
|
||||||
confidenceBuilder.setType(Protos.TransactionConfidence.Type.valueOf(confidence.getConfidenceType().getValue()));
|
writeConfidence(txBuilder, confidence, confidenceBuilder);
|
||||||
if (confidence.getConfidenceType() == ConfidenceType.BUILDING) {
|
|
||||||
confidenceBuilder.setAppearedAtHeight(confidence.getAppearedAtChainHeight());
|
|
||||||
}
|
|
||||||
if (confidence.getConfidenceType() == ConfidenceType.OVERRIDDEN_BY_DOUBLE_SPEND) {
|
|
||||||
confidenceBuilder.setOverridingTransaction(ByteString.copyFrom(confidence.getOverridingTransaction().getHash().getBytes()));
|
|
||||||
}
|
|
||||||
|
|
||||||
txBuilder.setConfidence(confidenceBuilder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return txBuilder.build();
|
return txBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void writeConfidence(
|
||||||
|
Protos.Transaction.Builder txBuilder,
|
||||||
|
TransactionConfidence confidence,
|
||||||
|
Protos.TransactionConfidence.Builder confidenceBuilder) {
|
||||||
|
confidenceBuilder.setType(
|
||||||
|
Protos.TransactionConfidence.Type.valueOf(confidence.getConfidenceType().getValue()));
|
||||||
|
if (confidence.getConfidenceType() == ConfidenceType.BUILDING) {
|
||||||
|
confidenceBuilder.setAppearedAtHeight(confidence.getAppearedAtChainHeight());
|
||||||
|
}
|
||||||
|
if (confidence.getConfidenceType() == ConfidenceType.OVERRIDDEN_BY_DOUBLE_SPEND) {
|
||||||
|
Sha256Hash overridingHash = confidence.getOverridingTransaction().getHash();
|
||||||
|
confidenceBuilder.setOverridingTransaction(hashToByteString(overridingHash));
|
||||||
|
}
|
||||||
|
|
||||||
|
txBuilder.setConfidence(confidenceBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteString hashToByteString(Sha256Hash hash) {
|
||||||
|
return ByteString.copyFrom(hash.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
public static Wallet readWallet(InputStream input, NetworkParameters params)
|
public static Wallet readWallet(InputStream input, NetworkParameters params)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
WalletProtobufSerializer serializer = new WalletProtobufSerializer();
|
WalletProtobufSerializer serializer = new WalletProtobufSerializer();
|
||||||
|
@ -175,7 +196,12 @@ public class WalletProtobufSerializer {
|
||||||
if (keyProto.getType() != Protos.Key.Type.ORIGINAL) {
|
if (keyProto.getType() != Protos.Key.Type.ORIGINAL) {
|
||||||
throw new IllegalArgumentException("Unknown key type in wallet");
|
throw new IllegalArgumentException("Unknown key type in wallet");
|
||||||
}
|
}
|
||||||
wallet.addKey(ECKey.fromPrivKeyBytes(keyProto.getPrivateKey().toByteArray()));
|
if (!keyProto.hasPrivateKey()) {
|
||||||
|
throw new IllegalArgumentException("Don't know how to handle pubkey-only keys");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] pubKey = keyProto.hasPublicKey() ? keyProto.getPublicKey().toByteArray() : null;
|
||||||
|
wallet.addKey(new ECKey(keyProto.getPrivateKey().toByteArray(), pubKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read all transactions and create outputs
|
// Read all transactions and create outputs
|
||||||
|
@ -205,7 +231,9 @@ public class WalletProtobufSerializer {
|
||||||
|
|
||||||
|
|
||||||
private void readTransaction(Protos.Transaction txProto, NetworkParameters params) {
|
private void readTransaction(Protos.Transaction txProto, NetworkParameters params) {
|
||||||
Transaction tx = new Transaction(params, txProto.getVersion(), new Sha256Hash(txProto.getHash().toByteArray()));
|
Transaction tx =
|
||||||
|
new Transaction(params, txProto.getVersion(),
|
||||||
|
new Sha256Hash(txProto.getHash().toByteArray()));
|
||||||
if (txProto.hasUpdatedAt())
|
if (txProto.hasUpdatedAt())
|
||||||
tx.setUpdateTime(new Date(txProto.getUpdatedAt()));
|
tx.setUpdateTime(new Date(txProto.getUpdatedAt()));
|
||||||
|
|
||||||
|
@ -270,17 +298,43 @@ public class WalletProtobufSerializer {
|
||||||
if(txProto.hasConfidence()) {
|
if(txProto.hasConfidence()) {
|
||||||
Protos.TransactionConfidence confidenceProto = txProto.getConfidence();
|
Protos.TransactionConfidence confidenceProto = txProto.getConfidence();
|
||||||
TransactionConfidence confidence = tx.getConfidence();
|
TransactionConfidence confidence = tx.getConfidence();
|
||||||
confidence.setConfidenceType(TransactionConfidence.ConfidenceType.valueOf(confidenceProto.getType().getNumber()));
|
readConfidence(tx, confidenceProto, confidence);
|
||||||
if (confidenceProto.hasAppearedAtHeight()) {
|
|
||||||
assert confidence.getConfidenceType() == ConfidenceType.BUILDING;
|
|
||||||
confidence.setAppearedAtChainHeight(confidenceProto.getAppearedAtHeight());
|
|
||||||
}
|
|
||||||
if (confidenceProto.hasOverridingTransaction()) {
|
|
||||||
assert confidence.getConfidenceType() == ConfidenceType.OVERRIDDEN_BY_DOUBLE_SPEND;
|
|
||||||
confidence.setOverridingTransaction(txMap.get(confidenceProto.getOverridingTransaction()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WalletTransaction(pool, tx);
|
return new WalletTransaction(pool, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readConfidence(
|
||||||
|
Transaction tx, Protos.TransactionConfidence confidenceProto,
|
||||||
|
TransactionConfidence confidence) {
|
||||||
|
// We are lenient here because tx confidence is not an essential part of the wallet.
|
||||||
|
// If the tx has an unknown type of confidence, ignore.
|
||||||
|
if (!confidenceProto.hasType()) {
|
||||||
|
log.warn("Unknown confidence type for tx {}", tx.getHashAsString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConfidenceType confidenceType =
|
||||||
|
TransactionConfidence.ConfidenceType.valueOf(confidenceProto.getType().getNumber());
|
||||||
|
confidence.setConfidenceType(confidenceType);
|
||||||
|
if (confidenceProto.hasAppearedAtHeight()) {
|
||||||
|
if (confidence.getConfidenceType() != ConfidenceType.BUILDING) {
|
||||||
|
log.warn("Have appearedAtHeight but not BUILDING for tx {}", tx.getHashAsString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confidence.setAppearedAtChainHeight(confidenceProto.getAppearedAtHeight());
|
||||||
|
}
|
||||||
|
if (confidenceProto.hasOverridingTransaction()) {
|
||||||
|
if (confidence.getConfidenceType() != ConfidenceType.OVERRIDDEN_BY_DOUBLE_SPEND) {
|
||||||
|
log.warn("Have overridingTransaction but not OVERRIDDEN for tx {}", tx.getHashAsString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Transaction overridingTransaction =
|
||||||
|
txMap.get(confidenceProto.getOverridingTransaction());
|
||||||
|
if (overridingTransaction == null) {
|
||||||
|
log.warn("Have overridingTransaction that is not in wallet for tx {}", tx.getHashAsString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confidence.setOverridingTransaction(overridingTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,23 @@ public final class Protos {
|
||||||
public interface KeyOrBuilder
|
public interface KeyOrBuilder
|
||||||
extends com.google.protobuf.MessageOrBuilder {
|
extends com.google.protobuf.MessageOrBuilder {
|
||||||
|
|
||||||
// required bytes private_key = 1;
|
// required .wallet.Key.Type type = 1;
|
||||||
boolean hasPrivateKey();
|
|
||||||
com.google.protobuf.ByteString getPrivateKey();
|
|
||||||
|
|
||||||
// required .wallet.Key.Type type = 2;
|
|
||||||
boolean hasType();
|
boolean hasType();
|
||||||
org.bitcoinj.wallet.Protos.Key.Type getType();
|
org.bitcoinj.wallet.Protos.Key.Type getType();
|
||||||
|
|
||||||
// optional string label = 3;
|
// optional bytes private_key = 2;
|
||||||
|
boolean hasPrivateKey();
|
||||||
|
com.google.protobuf.ByteString getPrivateKey();
|
||||||
|
|
||||||
|
// optional bytes public_key = 3;
|
||||||
|
boolean hasPublicKey();
|
||||||
|
com.google.protobuf.ByteString getPublicKey();
|
||||||
|
|
||||||
|
// optional string label = 4;
|
||||||
boolean hasLabel();
|
boolean hasLabel();
|
||||||
String getLabel();
|
String getLabel();
|
||||||
|
|
||||||
// optional int64 creation_timestamp = 4;
|
// optional int64 creation_timestamp = 5;
|
||||||
boolean hasCreationTimestamp();
|
boolean hasCreationTimestamp();
|
||||||
long getCreationTimestamp();
|
long getCreationTimestamp();
|
||||||
}
|
}
|
||||||
|
@ -122,31 +126,41 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int bitField0_;
|
private int bitField0_;
|
||||||
// required bytes private_key = 1;
|
// required .wallet.Key.Type type = 1;
|
||||||
public static final int PRIVATE_KEY_FIELD_NUMBER = 1;
|
public static final int TYPE_FIELD_NUMBER = 1;
|
||||||
private com.google.protobuf.ByteString privateKey_;
|
|
||||||
public boolean hasPrivateKey() {
|
|
||||||
return ((bitField0_ & 0x00000001) == 0x00000001);
|
|
||||||
}
|
|
||||||
public com.google.protobuf.ByteString getPrivateKey() {
|
|
||||||
return privateKey_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// required .wallet.Key.Type type = 2;
|
|
||||||
public static final int TYPE_FIELD_NUMBER = 2;
|
|
||||||
private org.bitcoinj.wallet.Protos.Key.Type type_;
|
private org.bitcoinj.wallet.Protos.Key.Type type_;
|
||||||
public boolean hasType() {
|
public boolean hasType() {
|
||||||
return ((bitField0_ & 0x00000002) == 0x00000002);
|
return ((bitField0_ & 0x00000001) == 0x00000001);
|
||||||
}
|
}
|
||||||
public org.bitcoinj.wallet.Protos.Key.Type getType() {
|
public org.bitcoinj.wallet.Protos.Key.Type getType() {
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string label = 3;
|
// optional bytes private_key = 2;
|
||||||
public static final int LABEL_FIELD_NUMBER = 3;
|
public static final int PRIVATE_KEY_FIELD_NUMBER = 2;
|
||||||
|
private com.google.protobuf.ByteString privateKey_;
|
||||||
|
public boolean hasPrivateKey() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
public com.google.protobuf.ByteString getPrivateKey() {
|
||||||
|
return privateKey_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional bytes public_key = 3;
|
||||||
|
public static final int PUBLIC_KEY_FIELD_NUMBER = 3;
|
||||||
|
private com.google.protobuf.ByteString publicKey_;
|
||||||
|
public boolean hasPublicKey() {
|
||||||
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
|
}
|
||||||
|
public com.google.protobuf.ByteString getPublicKey() {
|
||||||
|
return publicKey_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional string label = 4;
|
||||||
|
public static final int LABEL_FIELD_NUMBER = 4;
|
||||||
private java.lang.Object label_;
|
private java.lang.Object label_;
|
||||||
public boolean hasLabel() {
|
public boolean hasLabel() {
|
||||||
return ((bitField0_ & 0x00000004) == 0x00000004);
|
return ((bitField0_ & 0x00000008) == 0x00000008);
|
||||||
}
|
}
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
java.lang.Object ref = label_;
|
java.lang.Object ref = label_;
|
||||||
|
@ -174,19 +188,20 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional int64 creation_timestamp = 4;
|
// optional int64 creation_timestamp = 5;
|
||||||
public static final int CREATION_TIMESTAMP_FIELD_NUMBER = 4;
|
public static final int CREATION_TIMESTAMP_FIELD_NUMBER = 5;
|
||||||
private long creationTimestamp_;
|
private long creationTimestamp_;
|
||||||
public boolean hasCreationTimestamp() {
|
public boolean hasCreationTimestamp() {
|
||||||
return ((bitField0_ & 0x00000008) == 0x00000008);
|
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||||
}
|
}
|
||||||
public long getCreationTimestamp() {
|
public long getCreationTimestamp() {
|
||||||
return creationTimestamp_;
|
return creationTimestamp_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initFields() {
|
private void initFields() {
|
||||||
privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
|
||||||
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
||||||
|
privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
|
publicKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
label_ = "";
|
label_ = "";
|
||||||
creationTimestamp_ = 0L;
|
creationTimestamp_ = 0L;
|
||||||
}
|
}
|
||||||
|
@ -195,10 +210,6 @@ public final class Protos {
|
||||||
byte isInitialized = memoizedIsInitialized;
|
byte isInitialized = memoizedIsInitialized;
|
||||||
if (isInitialized != -1) return isInitialized == 1;
|
if (isInitialized != -1) return isInitialized == 1;
|
||||||
|
|
||||||
if (!hasPrivateKey()) {
|
|
||||||
memoizedIsInitialized = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!hasType()) {
|
if (!hasType()) {
|
||||||
memoizedIsInitialized = 0;
|
memoizedIsInitialized = 0;
|
||||||
return false;
|
return false;
|
||||||
|
@ -211,16 +222,19 @@ public final class Protos {
|
||||||
throws java.io.IOException {
|
throws java.io.IOException {
|
||||||
getSerializedSize();
|
getSerializedSize();
|
||||||
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
output.writeBytes(1, privateKey_);
|
output.writeEnum(1, type_.getNumber());
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
output.writeEnum(2, type_.getNumber());
|
output.writeBytes(2, privateKey_);
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
output.writeBytes(3, getLabelBytes());
|
output.writeBytes(3, publicKey_);
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
output.writeInt64(4, creationTimestamp_);
|
output.writeBytes(4, getLabelBytes());
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
|
output.writeInt64(5, creationTimestamp_);
|
||||||
}
|
}
|
||||||
getUnknownFields().writeTo(output);
|
getUnknownFields().writeTo(output);
|
||||||
}
|
}
|
||||||
|
@ -233,19 +247,23 @@ public final class Protos {
|
||||||
size = 0;
|
size = 0;
|
||||||
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
if (((bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeBytesSize(1, privateKey_);
|
.computeEnumSize(1, type_.getNumber());
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeEnumSize(2, type_.getNumber());
|
.computeBytesSize(2, privateKey_);
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeBytesSize(3, getLabelBytes());
|
.computeBytesSize(3, publicKey_);
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeInt64Size(4, creationTimestamp_);
|
.computeBytesSize(4, getLabelBytes());
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeInt64Size(5, creationTimestamp_);
|
||||||
}
|
}
|
||||||
size += getUnknownFields().getSerializedSize();
|
size += getUnknownFields().getSerializedSize();
|
||||||
memoizedSerializedSize = size;
|
memoizedSerializedSize = size;
|
||||||
|
@ -371,14 +389,16 @@ public final class Protos {
|
||||||
|
|
||||||
public Builder clear() {
|
public Builder clear() {
|
||||||
super.clear();
|
super.clear();
|
||||||
privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
|
||||||
bitField0_ = (bitField0_ & ~0x00000001);
|
|
||||||
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
|
privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
bitField0_ = (bitField0_ & ~0x00000002);
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
label_ = "";
|
publicKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
creationTimestamp_ = 0L;
|
label_ = "";
|
||||||
bitField0_ = (bitField0_ & ~0x00000008);
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
|
creationTimestamp_ = 0L;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000010);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,18 +440,22 @@ public final class Protos {
|
||||||
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
|
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
|
||||||
to_bitField0_ |= 0x00000001;
|
to_bitField0_ |= 0x00000001;
|
||||||
}
|
}
|
||||||
result.privateKey_ = privateKey_;
|
result.type_ = type_;
|
||||||
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
to_bitField0_ |= 0x00000002;
|
to_bitField0_ |= 0x00000002;
|
||||||
}
|
}
|
||||||
result.type_ = type_;
|
result.privateKey_ = privateKey_;
|
||||||
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
|
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
to_bitField0_ |= 0x00000004;
|
to_bitField0_ |= 0x00000004;
|
||||||
}
|
}
|
||||||
result.label_ = label_;
|
result.publicKey_ = publicKey_;
|
||||||
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
|
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
to_bitField0_ |= 0x00000008;
|
to_bitField0_ |= 0x00000008;
|
||||||
}
|
}
|
||||||
|
result.label_ = label_;
|
||||||
|
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
|
to_bitField0_ |= 0x00000010;
|
||||||
|
}
|
||||||
result.creationTimestamp_ = creationTimestamp_;
|
result.creationTimestamp_ = creationTimestamp_;
|
||||||
result.bitField0_ = to_bitField0_;
|
result.bitField0_ = to_bitField0_;
|
||||||
onBuilt();
|
onBuilt();
|
||||||
|
@ -449,11 +473,14 @@ public final class Protos {
|
||||||
|
|
||||||
public Builder mergeFrom(org.bitcoinj.wallet.Protos.Key other) {
|
public Builder mergeFrom(org.bitcoinj.wallet.Protos.Key other) {
|
||||||
if (other == org.bitcoinj.wallet.Protos.Key.getDefaultInstance()) return this;
|
if (other == org.bitcoinj.wallet.Protos.Key.getDefaultInstance()) return this;
|
||||||
|
if (other.hasType()) {
|
||||||
|
setType(other.getType());
|
||||||
|
}
|
||||||
if (other.hasPrivateKey()) {
|
if (other.hasPrivateKey()) {
|
||||||
setPrivateKey(other.getPrivateKey());
|
setPrivateKey(other.getPrivateKey());
|
||||||
}
|
}
|
||||||
if (other.hasType()) {
|
if (other.hasPublicKey()) {
|
||||||
setType(other.getType());
|
setPublicKey(other.getPublicKey());
|
||||||
}
|
}
|
||||||
if (other.hasLabel()) {
|
if (other.hasLabel()) {
|
||||||
setLabel(other.getLabel());
|
setLabel(other.getLabel());
|
||||||
|
@ -466,10 +493,6 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isInitialized() {
|
public final boolean isInitialized() {
|
||||||
if (!hasPrivateKey()) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!hasType()) {
|
if (!hasType()) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -500,29 +523,34 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 10: {
|
case 8: {
|
||||||
bitField0_ |= 0x00000001;
|
|
||||||
privateKey_ = input.readBytes();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 16: {
|
|
||||||
int rawValue = input.readEnum();
|
int rawValue = input.readEnum();
|
||||||
org.bitcoinj.wallet.Protos.Key.Type value = org.bitcoinj.wallet.Protos.Key.Type.valueOf(rawValue);
|
org.bitcoinj.wallet.Protos.Key.Type value = org.bitcoinj.wallet.Protos.Key.Type.valueOf(rawValue);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
unknownFields.mergeVarintField(2, rawValue);
|
unknownFields.mergeVarintField(1, rawValue);
|
||||||
} else {
|
} else {
|
||||||
bitField0_ |= 0x00000002;
|
bitField0_ |= 0x00000001;
|
||||||
type_ = value;
|
type_ = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 18: {
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
privateKey_ = input.readBytes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 26: {
|
case 26: {
|
||||||
bitField0_ |= 0x00000004;
|
bitField0_ |= 0x00000004;
|
||||||
|
publicKey_ = input.readBytes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 34: {
|
||||||
|
bitField0_ |= 0x00000008;
|
||||||
label_ = input.readBytes();
|
label_ = input.readBytes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 32: {
|
case 40: {
|
||||||
bitField0_ |= 0x00000008;
|
bitField0_ |= 0x00000010;
|
||||||
creationTimestamp_ = input.readInt64();
|
creationTimestamp_ = input.readInt64();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -532,34 +560,10 @@ public final class Protos {
|
||||||
|
|
||||||
private int bitField0_;
|
private int bitField0_;
|
||||||
|
|
||||||
// required bytes private_key = 1;
|
// required .wallet.Key.Type type = 1;
|
||||||
private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
|
||||||
public boolean hasPrivateKey() {
|
|
||||||
return ((bitField0_ & 0x00000001) == 0x00000001);
|
|
||||||
}
|
|
||||||
public com.google.protobuf.ByteString getPrivateKey() {
|
|
||||||
return privateKey_;
|
|
||||||
}
|
|
||||||
public Builder setPrivateKey(com.google.protobuf.ByteString value) {
|
|
||||||
if (value == null) {
|
|
||||||
throw new NullPointerException();
|
|
||||||
}
|
|
||||||
bitField0_ |= 0x00000001;
|
|
||||||
privateKey_ = value;
|
|
||||||
onChanged();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public Builder clearPrivateKey() {
|
|
||||||
bitField0_ = (bitField0_ & ~0x00000001);
|
|
||||||
privateKey_ = getDefaultInstance().getPrivateKey();
|
|
||||||
onChanged();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// required .wallet.Key.Type type = 2;
|
|
||||||
private org.bitcoinj.wallet.Protos.Key.Type type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
private org.bitcoinj.wallet.Protos.Key.Type type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
||||||
public boolean hasType() {
|
public boolean hasType() {
|
||||||
return ((bitField0_ & 0x00000002) == 0x00000002);
|
return ((bitField0_ & 0x00000001) == 0x00000001);
|
||||||
}
|
}
|
||||||
public org.bitcoinj.wallet.Protos.Key.Type getType() {
|
public org.bitcoinj.wallet.Protos.Key.Type getType() {
|
||||||
return type_;
|
return type_;
|
||||||
|
@ -568,22 +572,70 @@ public final class Protos {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
bitField0_ |= 0x00000002;
|
bitField0_ |= 0x00000001;
|
||||||
type_ = value;
|
type_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder clearType() {
|
public Builder clearType() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000002);
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional string label = 3;
|
// optional bytes private_key = 2;
|
||||||
|
private com.google.protobuf.ByteString privateKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
|
public boolean hasPrivateKey() {
|
||||||
|
return ((bitField0_ & 0x00000002) == 0x00000002);
|
||||||
|
}
|
||||||
|
public com.google.protobuf.ByteString getPrivateKey() {
|
||||||
|
return privateKey_;
|
||||||
|
}
|
||||||
|
public Builder setPrivateKey(com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000002;
|
||||||
|
privateKey_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Builder clearPrivateKey() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
|
privateKey_ = getDefaultInstance().getPrivateKey();
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional bytes public_key = 3;
|
||||||
|
private com.google.protobuf.ByteString publicKey_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
|
public boolean hasPublicKey() {
|
||||||
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
|
}
|
||||||
|
public com.google.protobuf.ByteString getPublicKey() {
|
||||||
|
return publicKey_;
|
||||||
|
}
|
||||||
|
public Builder setPublicKey(com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000004;
|
||||||
|
publicKey_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Builder clearPublicKey() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
|
publicKey_ = getDefaultInstance().getPublicKey();
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional string label = 4;
|
||||||
private java.lang.Object label_ = "";
|
private java.lang.Object label_ = "";
|
||||||
public boolean hasLabel() {
|
public boolean hasLabel() {
|
||||||
return ((bitField0_ & 0x00000004) == 0x00000004);
|
return ((bitField0_ & 0x00000008) == 0x00000008);
|
||||||
}
|
}
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
java.lang.Object ref = label_;
|
java.lang.Object ref = label_;
|
||||||
|
@ -599,39 +651,39 @@ public final class Protos {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
bitField0_ |= 0x00000004;
|
bitField0_ |= 0x00000008;
|
||||||
label_ = value;
|
label_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder clearLabel() {
|
public Builder clearLabel() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
label_ = getDefaultInstance().getLabel();
|
label_ = getDefaultInstance().getLabel();
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
void setLabel(com.google.protobuf.ByteString value) {
|
void setLabel(com.google.protobuf.ByteString value) {
|
||||||
bitField0_ |= 0x00000004;
|
bitField0_ |= 0x00000008;
|
||||||
label_ = value;
|
label_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional int64 creation_timestamp = 4;
|
// optional int64 creation_timestamp = 5;
|
||||||
private long creationTimestamp_ ;
|
private long creationTimestamp_ ;
|
||||||
public boolean hasCreationTimestamp() {
|
public boolean hasCreationTimestamp() {
|
||||||
return ((bitField0_ & 0x00000008) == 0x00000008);
|
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||||
}
|
}
|
||||||
public long getCreationTimestamp() {
|
public long getCreationTimestamp() {
|
||||||
return creationTimestamp_;
|
return creationTimestamp_;
|
||||||
}
|
}
|
||||||
public Builder setCreationTimestamp(long value) {
|
public Builder setCreationTimestamp(long value) {
|
||||||
bitField0_ |= 0x00000008;
|
bitField0_ |= 0x00000010;
|
||||||
creationTimestamp_ = value;
|
creationTimestamp_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder clearCreationTimestamp() {
|
public Builder clearCreationTimestamp() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000008);
|
bitField0_ = (bitField0_ & ~0x00000010);
|
||||||
creationTimestamp_ = 0L;
|
creationTimestamp_ = 0L;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
|
@ -1721,7 +1773,7 @@ public final class Protos {
|
||||||
public interface TransactionConfidenceOrBuilder
|
public interface TransactionConfidenceOrBuilder
|
||||||
extends com.google.protobuf.MessageOrBuilder {
|
extends com.google.protobuf.MessageOrBuilder {
|
||||||
|
|
||||||
// required .wallet.TransactionConfidence.Type type = 1;
|
// optional .wallet.TransactionConfidence.Type type = 1;
|
||||||
boolean hasType();
|
boolean hasType();
|
||||||
org.bitcoinj.wallet.Protos.TransactionConfidence.Type getType();
|
org.bitcoinj.wallet.Protos.TransactionConfidence.Type getType();
|
||||||
|
|
||||||
|
@ -1840,7 +1892,7 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int bitField0_;
|
private int bitField0_;
|
||||||
// required .wallet.TransactionConfidence.Type type = 1;
|
// optional .wallet.TransactionConfidence.Type type = 1;
|
||||||
public static final int TYPE_FIELD_NUMBER = 1;
|
public static final int TYPE_FIELD_NUMBER = 1;
|
||||||
private org.bitcoinj.wallet.Protos.TransactionConfidence.Type type_;
|
private org.bitcoinj.wallet.Protos.TransactionConfidence.Type type_;
|
||||||
public boolean hasType() {
|
public boolean hasType() {
|
||||||
|
@ -1880,10 +1932,6 @@ public final class Protos {
|
||||||
byte isInitialized = memoizedIsInitialized;
|
byte isInitialized = memoizedIsInitialized;
|
||||||
if (isInitialized != -1) return isInitialized == 1;
|
if (isInitialized != -1) return isInitialized == 1;
|
||||||
|
|
||||||
if (!hasType()) {
|
|
||||||
memoizedIsInitialized = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memoizedIsInitialized = 1;
|
memoizedIsInitialized = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2131,10 +2179,6 @@ public final class Protos {
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isInitialized() {
|
public final boolean isInitialized() {
|
||||||
if (!hasType()) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2188,7 +2232,7 @@ public final class Protos {
|
||||||
|
|
||||||
private int bitField0_;
|
private int bitField0_;
|
||||||
|
|
||||||
// required .wallet.TransactionConfidence.Type type = 1;
|
// optional .wallet.TransactionConfidence.Type type = 1;
|
||||||
private org.bitcoinj.wallet.Protos.TransactionConfidence.Type type_ = org.bitcoinj.wallet.Protos.TransactionConfidence.Type.UNKNOWN;
|
private org.bitcoinj.wallet.Protos.TransactionConfidence.Type type_ = org.bitcoinj.wallet.Protos.TransactionConfidence.Type.UNKNOWN;
|
||||||
public boolean hasType() {
|
public boolean hasType() {
|
||||||
return ((bitField0_ & 0x00000001) == 0x00000001);
|
return ((bitField0_ & 0x00000001) == 0x00000001);
|
||||||
|
@ -2590,12 +2634,6 @@ public final class Protos {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasConfidence()) {
|
|
||||||
if (!getConfidence().isInitialized()) {
|
|
||||||
memoizedIsInitialized = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memoizedIsInitialized = 1;
|
memoizedIsInitialized = 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3051,12 +3089,6 @@ public final class Protos {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasConfidence()) {
|
|
||||||
if (!getConfidence().isInitialized()) {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5639,39 +5671,40 @@ public final class Protos {
|
||||||
descriptor;
|
descriptor;
|
||||||
static {
|
static {
|
||||||
java.lang.String[] descriptorData = {
|
java.lang.String[] descriptorData = {
|
||||||
"\n\rbitcoin.proto\022\006wallet\"{\n\003Key\022\023\n\013privat" +
|
"\n\rbitcoin.proto\022\006wallet\"\217\001\n\003Key\022\036\n\004type\030" +
|
||||||
"e_key\030\001 \002(\014\022\036\n\004type\030\002 \002(\0162\020.wallet.Key.T" +
|
"\001 \002(\0162\020.wallet.Key.Type\022\023\n\013private_key\030\002" +
|
||||||
"ype\022\r\n\005label\030\003 \001(\t\022\032\n\022creation_timestamp" +
|
" \001(\014\022\022\n\npublic_key\030\003 \001(\014\022\r\n\005label\030\004 \001(\t\022" +
|
||||||
"\030\004 \001(\003\"\024\n\004Type\022\014\n\010ORIGINAL\020\001\"\203\001\n\020Transac" +
|
"\032\n\022creation_timestamp\030\005 \001(\003\"\024\n\004Type\022\014\n\010O" +
|
||||||
"tionInput\022\"\n\032transaction_out_point_hash\030" +
|
"RIGINAL\020\001\"\203\001\n\020TransactionInput\022\"\n\032transa" +
|
||||||
"\001 \002(\014\022#\n\033transaction_out_point_index\030\002 \002" +
|
"ction_out_point_hash\030\001 \002(\014\022#\n\033transactio" +
|
||||||
"(\005\022\024\n\014script_bytes\030\003 \002(\014\022\020\n\010sequence\030\004 \001" +
|
"n_out_point_index\030\002 \002(\005\022\024\n\014script_bytes\030" +
|
||||||
"(\r\"\177\n\021TransactionOutput\022\r\n\005value\030\001 \002(\003\022\024" +
|
"\003 \002(\014\022\020\n\010sequence\030\004 \001(\r\"\177\n\021TransactionOu" +
|
||||||
"\n\014script_bytes\030\002 \002(\014\022!\n\031spent_by_transac" +
|
"tput\022\r\n\005value\030\001 \002(\003\022\024\n\014script_bytes\030\002 \002(" +
|
||||||
"tion_hash\030\003 \001(\014\022\"\n\032spent_by_transaction_",
|
"\014\022!\n\031spent_by_transaction_hash\030\003 \001(\014\022\"\n\032",
|
||||||
"index\030\004 \001(\005\"\366\001\n\025TransactionConfidence\0220\n" +
|
"spent_by_transaction_index\030\004 \001(\005\"\366\001\n\025Tra" +
|
||||||
"\004type\030\001 \002(\0162\".wallet.TransactionConfiden" +
|
"nsactionConfidence\0220\n\004type\030\001 \001(\0162\".walle" +
|
||||||
"ce.Type\022\032\n\022appeared_at_height\030\002 \001(\005\022\036\n\026o" +
|
"t.TransactionConfidence.Type\022\032\n\022appeared" +
|
||||||
"verriding_transaction\030\003 \001(\014\"o\n\004Type\022\013\n\007U" +
|
"_at_height\030\002 \001(\005\022\036\n\026overriding_transacti" +
|
||||||
"NKNOWN\020\000\022\014\n\010BUILDING\020\001\022\025\n\021NOT_SEEN_IN_CH" +
|
"on\030\003 \001(\014\"o\n\004Type\022\013\n\007UNKNOWN\020\000\022\014\n\010BUILDIN" +
|
||||||
"AIN\020\002\022\025\n\021NOT_IN_BEST_CHAIN\020\003\022\036\n\032OVERRIDD" +
|
"G\020\001\022\025\n\021NOT_SEEN_IN_CHAIN\020\002\022\025\n\021NOT_IN_BES" +
|
||||||
"EN_BY_DOUBLE_SPEND\020\004\"\211\003\n\013Transaction\022\017\n\007" +
|
"T_CHAIN\020\003\022\036\n\032OVERRIDDEN_BY_DOUBLE_SPEND\020" +
|
||||||
"version\030\001 \002(\005\022\014\n\004hash\030\002 \002(\014\022&\n\004pool\030\003 \002(" +
|
"\004\"\211\003\n\013Transaction\022\017\n\007version\030\001 \002(\005\022\014\n\004ha" +
|
||||||
"\0162\030.wallet.Transaction.Pool\022\021\n\tlock_time" +
|
"sh\030\002 \002(\014\022&\n\004pool\030\003 \002(\0162\030.wallet.Transact" +
|
||||||
"\030\004 \001(\r\022\022\n\nupdated_at\030\005 \001(\003\0223\n\021transactio",
|
"ion.Pool\022\021\n\tlock_time\030\004 \001(\r\022\022\n\nupdated_a",
|
||||||
"n_input\030\006 \003(\0132\030.wallet.TransactionInput\022" +
|
"t\030\005 \001(\003\0223\n\021transaction_input\030\006 \003(\0132\030.wal" +
|
||||||
"5\n\022transaction_output\030\007 \003(\0132\031.wallet.Tra" +
|
"let.TransactionInput\0225\n\022transaction_outp" +
|
||||||
"nsactionOutput\022\022\n\nblock_hash\030\010 \003(\014\0221\n\nco" +
|
"ut\030\007 \003(\0132\031.wallet.TransactionOutput\022\022\n\nb" +
|
||||||
"nfidence\030\t \001(\0132\035.wallet.TransactionConfi" +
|
"lock_hash\030\010 \003(\014\0221\n\nconfidence\030\t \001(\0132\035.wa" +
|
||||||
"dence\"Y\n\004Pool\022\013\n\007UNSPENT\020\004\022\t\n\005SPENT\020\005\022\014\n" +
|
"llet.TransactionConfidence\"Y\n\004Pool\022\013\n\007UN" +
|
||||||
"\010INACTIVE\020\002\022\010\n\004DEAD\020\n\022\013\n\007PENDING\020\020\022\024\n\020PE" +
|
"SPENT\020\004\022\t\n\005SPENT\020\005\022\014\n\010INACTIVE\020\002\022\010\n\004DEAD" +
|
||||||
"NDING_INACTIVE\020\022\"8\n\tExtension\022\n\n\002id\030\001 \002(" +
|
"\020\n\022\013\n\007PENDING\020\020\022\024\n\020PENDING_INACTIVE\020\022\"8\n" +
|
||||||
"\t\022\014\n\004data\030\002 \002(\014\022\021\n\tmandatory\030\003 \002(\010\"\254\001\n\006W" +
|
"\tExtension\022\n\n\002id\030\001 \002(\t\022\014\n\004data\030\002 \002(\014\022\021\n\t" +
|
||||||
"allet\022\032\n\022network_identifier\030\001 \002(\t\022\034\n\024las" +
|
"mandatory\030\003 \002(\010\"\254\001\n\006Wallet\022\032\n\022network_id" +
|
||||||
"t_seen_block_hash\030\002 \001(\014\022\030\n\003key\030\003 \003(\0132\013.w",
|
"entifier\030\001 \002(\t\022\034\n\024last_seen_block_hash\030\002",
|
||||||
"allet.Key\022(\n\013transaction\030\004 \003(\0132\023.wallet." +
|
" \001(\014\022\030\n\003key\030\003 \003(\0132\013.wallet.Key\022(\n\013transa" +
|
||||||
"Transaction\022$\n\textension\030\n \003(\0132\021.wallet." +
|
"ction\030\004 \003(\0132\023.wallet.Transaction\022$\n\texte" +
|
||||||
"ExtensionB\035\n\023org.bitcoinj.walletB\006Protos"
|
"nsion\030\n \003(\0132\021.wallet.ExtensionB\035\n\023org.bi" +
|
||||||
|
"tcoinj.walletB\006Protos"
|
||||||
};
|
};
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||||
|
@ -5683,7 +5716,7 @@ public final class Protos {
|
||||||
internal_static_wallet_Key_fieldAccessorTable = new
|
internal_static_wallet_Key_fieldAccessorTable = new
|
||||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||||
internal_static_wallet_Key_descriptor,
|
internal_static_wallet_Key_descriptor,
|
||||||
new java.lang.String[] { "PrivateKey", "Type", "Label", "CreationTimestamp", },
|
new java.lang.String[] { "Type", "PrivateKey", "PublicKey", "Label", "CreationTimestamp", },
|
||||||
org.bitcoinj.wallet.Protos.Key.class,
|
org.bitcoinj.wallet.Protos.Key.class,
|
||||||
org.bitcoinj.wallet.Protos.Key.Builder.class);
|
org.bitcoinj.wallet.Protos.Key.Builder.class);
|
||||||
internal_static_wallet_TransactionInput_descriptor =
|
internal_static_wallet_TransactionInput_descriptor =
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ECKeyTest {
|
||||||
// Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
|
// Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
|
||||||
// a message with it.
|
// a message with it.
|
||||||
BigInteger privkey = new BigInteger(1, Hex.decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
|
BigInteger privkey = new BigInteger(1, Hex.decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
|
||||||
ECKey key = new ECKey(privkey, null);
|
ECKey key = new ECKey(privkey);
|
||||||
byte[] message = new byte[32]; // All zeroes.
|
byte[] message = new byte[32]; // All zeroes.
|
||||||
byte[] output = key.sign(message);
|
byte[] output = key.sign(message);
|
||||||
assertTrue(key.verify(message, output));
|
assertTrue(key.verify(message, output));
|
||||||
|
@ -70,6 +70,35 @@ public class ECKeyTest {
|
||||||
assertTrue(decodedKey.verify(message, roundtripKey.sign(message)));
|
assertTrue(decodedKey.verify(message, roundtripKey.sign(message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKeyPairRoundtrip() {
|
||||||
|
byte[] privkeyASN1 = Hex.decode(
|
||||||
|
"3082011302010104205c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4aa081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200042af7a2aafe8dafd7dc7f9cfb58ce09bda7dce28653ab229b98d1d3d759660c672dd0db18c8c2d76aa470448e876fc2089ab1354c01a6e72cefc50915f4a963ee");
|
||||||
|
ECKey decodedKey = ECKey.fromASN1(privkeyASN1);
|
||||||
|
|
||||||
|
// Now re-encode and decode the ASN.1 to see if it is equivalent (it does not produce the exact same byte
|
||||||
|
// sequence, some integers are padded now).
|
||||||
|
ECKey roundtripKey =
|
||||||
|
new ECKey(decodedKey.getPrivKeyBytes(), decodedKey.getPubKey());
|
||||||
|
|
||||||
|
for (ECKey key : new ECKey[] {decodedKey, roundtripKey}) {
|
||||||
|
byte[] message = reverseBytes(Hex.decode(
|
||||||
|
"11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
|
||||||
|
byte[] output = key.sign(message);
|
||||||
|
assertTrue(key.verify(message, output));
|
||||||
|
|
||||||
|
output = Hex.decode(
|
||||||
|
"304502206faa2ebc614bf4a0b31f0ce4ed9012eb193302ec2bcaccc7ae8bb40577f47549022100c73a1a1acc209f3f860bf9b9f5e13e9433db6f8b7bd527a088a0e0cd0a4c83e9");
|
||||||
|
assertTrue(key.verify(message, output));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to sign with one key and verify with the other.
|
||||||
|
byte[] message = reverseBytes(Hex.decode(
|
||||||
|
"11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
|
||||||
|
assertTrue(roundtripKey.verify(message, decodedKey.sign(message)));
|
||||||
|
assertTrue(decodedKey.verify(message, roundtripKey.sign(message)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void base58Encoding() throws Exception {
|
public void base58Encoding() throws Exception {
|
||||||
String addr = "mqAJmaxMcG5pPHHc3H3NtyXzY7kGbJLuMF";
|
String addr = "mqAJmaxMcG5pPHHc3H3NtyXzY7kGbJLuMF";
|
||||||
|
|
Loading…
Add table
Reference in a new issue