mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-14 19:25:51 +00:00
Allow to create wallets with an arbitrary account path. Adds a test for BIP44 wallets (account zero only).
Authors: Nelson MELINA <nelson.melina@mycelium.com>, Giuseppe Magnotta <giuseppe.magnotta@gmail.com>
This commit is contained in:
parent
61e5d714c3
commit
e036f8174a
@ -81,11 +81,21 @@ public final class HDKeyDerivation {
|
||||
/**
|
||||
* @throws HDDerivationException if privKeyBytes is invalid (0 or >= n).
|
||||
*/
|
||||
public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException {
|
||||
public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode)
|
||||
throws HDDerivationException {
|
||||
// childNumberPath is an empty list because we are creating the root key.
|
||||
return createMasterPrivKeyFromBytes(privKeyBytes, chainCode, ImmutableList.<ChildNumber> of());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws HDDerivationException if privKeyBytes is invalid (0 or >= n).
|
||||
*/
|
||||
public static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode,
|
||||
ImmutableList<ChildNumber> childNumberPath) throws HDDerivationException {
|
||||
BigInteger priv = new BigInteger(1, privKeyBytes);
|
||||
assertNonZero(priv, "Generated master key is invalid.");
|
||||
assertLessThanN(priv, "Generated master key is invalid.");
|
||||
return new DeterministicKey(ImmutableList.<ChildNumber>of(), chainCode, priv, null);
|
||||
return new DeterministicKey(childNumberPath, chainCode, priv, null);
|
||||
}
|
||||
|
||||
public static DeterministicKey createMasterPubKeyFromBytes(byte[] pubKeyBytes, byte[] chainCode) {
|
||||
|
@ -18,6 +18,8 @@ package org.bitcoinj.wallet;
|
||||
|
||||
import org.bitcoinj.crypto.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* Default factory for creating keychains while de-serializing.
|
||||
*/
|
||||
@ -32,17 +34,25 @@ public class DefaultKeyChainFactory implements KeyChainFactory {
|
||||
return chain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed,
|
||||
KeyCrypter crypter, boolean isMarried, ImmutableList<ChildNumber> accountPath) {
|
||||
DeterministicKeyChain chain;
|
||||
if (isMarried)
|
||||
chain = new MarriedKeyChain(seed, crypter);
|
||||
else
|
||||
chain = new DeterministicKeyChain(seed, crypter, accountPath);
|
||||
return chain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain makeWatchingKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicKey accountKey,
|
||||
boolean isFollowingKey, boolean isMarried) throws UnreadableWalletException {
|
||||
if (!accountKey.getPath().equals(DeterministicKeyChain.ACCOUNT_ZERO_PATH))
|
||||
throw new UnreadableWalletException("Expecting account key but found key with path: " +
|
||||
HDUtils.formatPath(accountKey.getPath()));
|
||||
DeterministicKeyChain chain;
|
||||
if (isMarried)
|
||||
chain = new MarriedKeyChain(accountKey);
|
||||
else
|
||||
chain = new DeterministicKeyChain(accountKey, isFollowingKey);
|
||||
chain = new DeterministicKeyChain(accountKey, isFollowingKey, accountKey.getPath());
|
||||
return chain;
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
private DeterministicHierarchy hierarchy;
|
||||
@Nullable private DeterministicKey rootKey;
|
||||
@Nullable private DeterministicSeed seed;
|
||||
@Nullable private ImmutableList<ChildNumber> accountPath;
|
||||
|
||||
// Paths through the key tree. External keys are ones that are communicated to other parties. Internal keys are
|
||||
// keys created for change addresses, coinbases, mixing, etc - anything that isn't communicated. The distinction
|
||||
@ -113,13 +114,11 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
// a payment request that can generate lots of addresses independently.
|
||||
// The account path may be overridden by subclasses.
|
||||
public static final ImmutableList<ChildNumber> ACCOUNT_ZERO_PATH = ImmutableList.of(ChildNumber.ZERO_HARDENED);
|
||||
// m / 44' / 0' / 0'
|
||||
public static final ImmutableList<ChildNumber> BIP44_ACCOUNT_ZERO_PATH = ImmutableList.of(new ChildNumber(44, true),
|
||||
ChildNumber.ZERO_HARDENED, ChildNumber.ZERO_HARDENED);
|
||||
public static final ImmutableList<ChildNumber> EXTERNAL_SUBPATH = ImmutableList.of(ChildNumber.ZERO);
|
||||
public static final ImmutableList<ChildNumber> INTERNAL_SUBPATH = ImmutableList.of(ChildNumber.ONE);
|
||||
public static final ImmutableList<ChildNumber> EXTERNAL_PATH = HDUtils.concat(ACCOUNT_ZERO_PATH, EXTERNAL_SUBPATH);
|
||||
public static final ImmutableList<ChildNumber> INTERNAL_PATH = HDUtils.concat(ACCOUNT_ZERO_PATH, INTERNAL_SUBPATH);
|
||||
// m / 44' / 0' / 0'
|
||||
public static final ImmutableList<ChildNumber> BIP44_ACCOUNT_ZERO_PATH =
|
||||
ImmutableList.of(new ChildNumber(44, true), ChildNumber.ZERO_HARDENED, ChildNumber.ZERO_HARDENED);
|
||||
|
||||
// We try to ensure we have at least this many keys ready and waiting to be handed out via getKey().
|
||||
// See docs for getLookaheadSize() for more info on what this is for. The -1 value means it hasn't been calculated
|
||||
@ -307,17 +306,33 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
* if the starting seed is the same.
|
||||
*/
|
||||
protected DeterministicKeyChain(DeterministicSeed seed) {
|
||||
this(seed, null);
|
||||
this(seed, null, ACCOUNT_ZERO_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deterministic key chain starting from the given seed. This deterministic Key chain
|
||||
* will follow the account path defined.
|
||||
*/
|
||||
public DeterministicKeyChain(DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
|
||||
this(seed, null, accountPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deterministic key chain that watches the given (public only) root key. You can use this to calculate
|
||||
* balances and generally follow along, but spending is not possible with such a chain. Currently you can't use
|
||||
* this method to watch an arbitrary fragment of some other tree, this limitation may be removed in future.
|
||||
* balances and generally follow along, but spending is not possible with such a chain.
|
||||
*/
|
||||
public DeterministicKeyChain(DeterministicKey watchingKey) {
|
||||
this(watchingKey, ACCOUNT_ZERO_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deterministic key chain that watches the given (public only) root key. You can use this to calculate
|
||||
* balances and generally follow along, but spending is not possible with such a chain.
|
||||
*/
|
||||
public DeterministicKeyChain(DeterministicKey watchingKey, ImmutableList<ChildNumber> accountPath) {
|
||||
checkArgument(watchingKey.isPubKeyOnly(), "Private subtrees not currently supported: if you got this key from DKC.getWatchingKey() then use .dropPrivate().dropParent() on it first.");
|
||||
checkArgument(watchingKey.getPath().size() == getAccountPath().size(), "You can only watch an account key currently");
|
||||
checkArgument(watchingKey.getPath().size() == accountPath.size(), "You can only watch an account key currently");
|
||||
setAccountPath(accountPath);
|
||||
basicKeyChain = new BasicKeyChain();
|
||||
this.seed = null;
|
||||
this.rootKey = null;
|
||||
@ -332,7 +347,17 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
* <p>Watch key has to be an account key.</p>
|
||||
*/
|
||||
protected DeterministicKeyChain(DeterministicKey watchKey, boolean isFollowing) {
|
||||
this(watchKey);
|
||||
this(watchKey, isFollowing, ACCOUNT_ZERO_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a deterministic key chain with the given watch key. If <code>isFollowing</code> flag is set then this keychain follows
|
||||
* some other keychain. In a married wallet following keychain represents "spouse's" keychain.</p>
|
||||
* <p>Watch key has to be an account key.</p>
|
||||
*/
|
||||
protected DeterministicKeyChain(DeterministicKey watchKey, boolean isFollowing,
|
||||
ImmutableList<ChildNumber> accountPath) {
|
||||
this(watchKey, accountPath);
|
||||
this.isFollowing = isFollowing;
|
||||
}
|
||||
|
||||
@ -349,13 +374,30 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
* Creates a key chain that watches the given account key.
|
||||
*/
|
||||
public static DeterministicKeyChain watch(DeterministicKey accountKey) {
|
||||
return new DeterministicKeyChain(accountKey);
|
||||
return watch(accountKey, ACCOUNT_ZERO_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a key chain that watches the given account key.
|
||||
*/
|
||||
public static DeterministicKeyChain watch(DeterministicKey accountKey, ImmutableList<ChildNumber> accountPath) {
|
||||
return new DeterministicKeyChain(accountKey, accountPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use in {@link KeyChainFactory} during deserialization.
|
||||
*/
|
||||
protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter) {
|
||||
this(seed, crypter, ACCOUNT_ZERO_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deterministic key chain with an encrypted deterministic seed using the provided account path.
|
||||
* Using {@link org.bitcoinj.crypto.KeyCrypter KeyCrypter} to decrypt.
|
||||
*/
|
||||
protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter,
|
||||
ImmutableList<ChildNumber> accountPath) {
|
||||
setAccountPath(accountPath);
|
||||
this.seed = seed;
|
||||
basicKeyChain = new BasicKeyChain(crypter);
|
||||
if (!seed.isEncrypted()) {
|
||||
@ -421,9 +463,16 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
|
||||
/** Override in subclasses to use a different account derivation path */
|
||||
protected ImmutableList<ChildNumber> getAccountPath() {
|
||||
if (accountPath != null)
|
||||
return accountPath;
|
||||
return ACCOUNT_ZERO_PATH;
|
||||
}
|
||||
|
||||
/** Store account path of this DeterministicKey */
|
||||
protected void setAccountPath(ImmutableList<ChildNumber> accountPath) {
|
||||
this.accountPath = accountPath;
|
||||
}
|
||||
|
||||
private DeterministicKey encryptNonLeaf(KeyParameter aesKey, DeterministicKeyChain chain,
|
||||
DeterministicKey parent, ImmutableList<ChildNumber> path) {
|
||||
DeterministicKey key = chain.hierarchy.get(path, false, false);
|
||||
@ -729,6 +778,9 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
Protos.Key.Builder mnemonicEntry = BasicKeyChain.serializeEncryptableItem(seed);
|
||||
mnemonicEntry.setType(Protos.Key.Type.DETERMINISTIC_MNEMONIC);
|
||||
serializeSeedEncryptableItem(seed, mnemonicEntry);
|
||||
for (ChildNumber childNumber : getAccountPath()) {
|
||||
mnemonicEntry.addAccountPath(childNumber.i());
|
||||
}
|
||||
entries.add(mnemonicEntry.build());
|
||||
}
|
||||
Map<ECKey, Protos.Key.Builder> keys = basicKeyChain.serializeToEditableProtobufs();
|
||||
@ -778,11 +830,18 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
int lookaheadSize = -1;
|
||||
int sigsRequiredToSpend = 1;
|
||||
|
||||
List<ChildNumber> accountPath = newArrayList();
|
||||
PeekingIterator<Protos.Key> iter = Iterators.peekingIterator(keys.iterator());
|
||||
while (iter.hasNext()) {
|
||||
Protos.Key key = iter.next();
|
||||
final Protos.Key.Type t = key.getType();
|
||||
if (t == Protos.Key.Type.DETERMINISTIC_MNEMONIC) {
|
||||
accountPath = newArrayList();
|
||||
for (int i : key.getAccountPathList()) {
|
||||
accountPath.add(new ChildNumber(i));
|
||||
}
|
||||
if (accountPath.isEmpty())
|
||||
accountPath = ACCOUNT_ZERO_PATH;
|
||||
if (chain != null) {
|
||||
checkState(lookaheadSize >= 0);
|
||||
chain.setLookaheadSize(lookaheadSize);
|
||||
@ -855,7 +914,8 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
chain = factory.makeWatchingKeyChain(key, iter.peek(), accountKey, isFollowingKey, isMarried);
|
||||
isWatchingAccountKey = true;
|
||||
} else {
|
||||
chain = factory.makeKeyChain(key, iter.peek(), seed, crypter, isMarried);
|
||||
chain = factory.makeKeyChain(key, iter.peek(), seed, crypter, isMarried,
|
||||
ImmutableList.<ChildNumber> builder().addAll(accountPath).build());
|
||||
chain.lookaheadSize = LAZY_CALCULATE_LOOKAHEAD;
|
||||
// If the seed is encrypted, then the chain is incomplete at this point. However, we will load
|
||||
// it up below as we parse in the keys. We just need to check at the end that we've loaded
|
||||
@ -896,19 +956,25 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
||||
// been rederived and inserted at this point. In the encrypted case though,
|
||||
// we can't rederive and we must reinsert, potentially building the hierarchy object
|
||||
// if need be.
|
||||
if (path.size() == 0) {
|
||||
if (path.isEmpty()) {
|
||||
// Master key.
|
||||
if (chain.rootKey == null) {
|
||||
chain.rootKey = detkey;
|
||||
chain.hierarchy = new DeterministicHierarchy(detkey);
|
||||
}
|
||||
} else if (path.size() == chain.getAccountPath().size() + 1) {
|
||||
// Constant 0 is used for external chain and constant 1 for internal chain
|
||||
// (also known as change addresses). https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
||||
if (detkey.getChildNumber().num() == 0) {
|
||||
// External chain is used for addresses that are meant to be visible outside of the wallet
|
||||
// (e.g. for receiving payments).
|
||||
chain.externalParentKey = detkey;
|
||||
chain.issuedExternalKeys = key.getDeterministicKey().getIssuedSubkeys();
|
||||
lookaheadSize = Math.max(lookaheadSize, key.getDeterministicKey().getLookaheadSize());
|
||||
sigsRequiredToSpend = key.getDeterministicKey().getSigsRequiredToSpend();
|
||||
} else if (detkey.getChildNumber().num() == 1) {
|
||||
// Internal chain is used for addresses which are not meant to be visible outside of the
|
||||
// wallet and is used for return transaction change.
|
||||
chain.internalParentKey = detkey;
|
||||
chain.issuedInternalKeys = key.getDeterministicKey().getIssuedSubkeys();
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.bitcoinj.wallet;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.bitcoinj.crypto.ChildNumber;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
|
||||
@ -34,6 +36,20 @@ public interface KeyChainFactory {
|
||||
*/
|
||||
DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried);
|
||||
|
||||
/**
|
||||
* Make a keychain (but not a watching one) with the specified account path
|
||||
*
|
||||
* @param key the protobuf for the root key
|
||||
* @param firstSubKey the protobuf for the first child key (normally the parent of the external subchain)
|
||||
* @param seed the seed
|
||||
* @param crypter the encrypted/decrypter
|
||||
* @param isMarried whether the keychain is leading in a marriage
|
||||
* @param accountPath the specified account path
|
||||
*/
|
||||
DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed,
|
||||
KeyCrypter crypter, boolean isMarried,
|
||||
ImmutableList<ChildNumber> accountPath);
|
||||
|
||||
/**
|
||||
* Make a watching keychain.
|
||||
*
|
||||
|
@ -84,6 +84,14 @@ public class KeyChainGroup implements KeyBag {
|
||||
this(params, null, ImmutableList.of(new DeterministicKeyChain(seed)), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain initialized from the given seed. Account path is
|
||||
* provided.
|
||||
*/
|
||||
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
|
||||
this(params, null, ImmutableList.of(new DeterministicKeyChain(seed, accountPath)), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key.
|
||||
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
|
||||
@ -92,6 +100,14 @@ public class KeyChainGroup implements KeyBag {
|
||||
this(params, null, ImmutableList.of(DeterministicKeyChain.watch(watchKey)), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key.
|
||||
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
|
||||
*/
|
||||
public KeyChainGroup(NetworkParameters params, DeterministicKey watchKey, ImmutableList<ChildNumber> accountPath) {
|
||||
this(params, null, ImmutableList.of(DeterministicKeyChain.watch(watchKey, accountPath)), null, null);
|
||||
}
|
||||
|
||||
// Used for deserialization.
|
||||
private KeyChainGroup(NetworkParameters params, @Nullable BasicKeyChain basicKeyChain, List<DeterministicKeyChain> chains,
|
||||
@Nullable EnumMap<KeyChain.KeyPurpose, DeterministicKey> currentKeys, @Nullable KeyCrypter crypter) {
|
||||
|
@ -2476,6 +2476,31 @@ public final class Protos {
|
||||
* </pre>
|
||||
*/
|
||||
org.bitcoinj.wallet.Protos.EncryptedDataOrBuilder getEncryptedDeterministicSeedOrBuilder();
|
||||
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
java.util.List<java.lang.Integer> getAccountPathList();
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
int getAccountPathCount();
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
int getAccountPath(int index);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code wallet.Key}
|
||||
@ -2614,6 +2639,27 @@ public final class Protos {
|
||||
bitField0_ |= 0x00000100;
|
||||
break;
|
||||
}
|
||||
case 80: {
|
||||
if (!((mutable_bitField0_ & 0x00000200) == 0x00000200)) {
|
||||
accountPath_ = new java.util.ArrayList<java.lang.Integer>();
|
||||
mutable_bitField0_ |= 0x00000200;
|
||||
}
|
||||
accountPath_.add(input.readUInt32());
|
||||
break;
|
||||
}
|
||||
case 82: {
|
||||
int length = input.readRawVarint32();
|
||||
int limit = input.pushLimit(length);
|
||||
if (!((mutable_bitField0_ & 0x00000200) == 0x00000200) && input.getBytesUntilLimit() > 0) {
|
||||
accountPath_ = new java.util.ArrayList<java.lang.Integer>();
|
||||
mutable_bitField0_ |= 0x00000200;
|
||||
}
|
||||
while (input.getBytesUntilLimit() > 0) {
|
||||
accountPath_.add(input.readUInt32());
|
||||
}
|
||||
input.popLimit(limit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
@ -2622,6 +2668,9 @@ public final class Protos {
|
||||
throw new com.google.protobuf.InvalidProtocolBufferException(
|
||||
e.getMessage()).setUnfinishedMessage(this);
|
||||
} finally {
|
||||
if (((mutable_bitField0_ & 0x00000200) == 0x00000200)) {
|
||||
accountPath_ = java.util.Collections.unmodifiableList(accountPath_);
|
||||
}
|
||||
this.unknownFields = unknownFields.build();
|
||||
makeExtensionsImmutable();
|
||||
}
|
||||
@ -3056,6 +3105,41 @@ public final class Protos {
|
||||
return encryptedDeterministicSeed_;
|
||||
}
|
||||
|
||||
public static final int ACCOUNT_PATH_FIELD_NUMBER = 10;
|
||||
private java.util.List<java.lang.Integer> accountPath_;
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public java.util.List<java.lang.Integer>
|
||||
getAccountPathList() {
|
||||
return accountPath_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public int getAccountPathCount() {
|
||||
return accountPath_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public int getAccountPath(int index) {
|
||||
return accountPath_.get(index);
|
||||
}
|
||||
private int accountPathMemoizedSerializedSize = -1;
|
||||
|
||||
private void initFields() {
|
||||
type_ = org.bitcoinj.wallet.Protos.Key.Type.ORIGINAL;
|
||||
secretBytes_ = com.google.protobuf.ByteString.EMPTY;
|
||||
@ -3066,6 +3150,7 @@ public final class Protos {
|
||||
deterministicKey_ = org.bitcoinj.wallet.Protos.DeterministicKey.getDefaultInstance();
|
||||
deterministicSeed_ = com.google.protobuf.ByteString.EMPTY;
|
||||
encryptedDeterministicSeed_ = org.bitcoinj.wallet.Protos.EncryptedData.getDefaultInstance();
|
||||
accountPath_ = java.util.Collections.emptyList();
|
||||
}
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
@ -3129,6 +3214,13 @@ public final class Protos {
|
||||
if (((bitField0_ & 0x00000100) == 0x00000100)) {
|
||||
output.writeMessage(9, encryptedDeterministicSeed_);
|
||||
}
|
||||
if (getAccountPathList().size() > 0) {
|
||||
output.writeRawVarint32(82);
|
||||
output.writeRawVarint32(accountPathMemoizedSerializedSize);
|
||||
}
|
||||
for (int i = 0; i < accountPath_.size(); i++) {
|
||||
output.writeUInt32NoTag(accountPath_.get(i));
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@ -3174,6 +3266,20 @@ public final class Protos {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeMessageSize(9, encryptedDeterministicSeed_);
|
||||
}
|
||||
{
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < accountPath_.size(); i++) {
|
||||
dataSize += com.google.protobuf.CodedOutputStream
|
||||
.computeUInt32SizeNoTag(accountPath_.get(i));
|
||||
}
|
||||
size += dataSize;
|
||||
if (!getAccountPathList().isEmpty()) {
|
||||
size += 1;
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt32SizeNoTag(dataSize);
|
||||
}
|
||||
accountPathMemoizedSerializedSize = dataSize;
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
@ -3333,6 +3439,8 @@ public final class Protos {
|
||||
encryptedDeterministicSeedBuilder_.clear();
|
||||
}
|
||||
bitField0_ = (bitField0_ & ~0x00000100);
|
||||
accountPath_ = java.util.Collections.emptyList();
|
||||
bitField0_ = (bitField0_ & ~0x00000200);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -3409,6 +3517,11 @@ public final class Protos {
|
||||
} else {
|
||||
result.encryptedDeterministicSeed_ = encryptedDeterministicSeedBuilder_.build();
|
||||
}
|
||||
if (((bitField0_ & 0x00000200) == 0x00000200)) {
|
||||
accountPath_ = java.util.Collections.unmodifiableList(accountPath_);
|
||||
bitField0_ = (bitField0_ & ~0x00000200);
|
||||
}
|
||||
result.accountPath_ = accountPath_;
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
@ -3454,6 +3567,16 @@ public final class Protos {
|
||||
if (other.hasEncryptedDeterministicSeed()) {
|
||||
mergeEncryptedDeterministicSeed(other.getEncryptedDeterministicSeed());
|
||||
}
|
||||
if (!other.accountPath_.isEmpty()) {
|
||||
if (accountPath_.isEmpty()) {
|
||||
accountPath_ = other.accountPath_;
|
||||
bitField0_ = (bitField0_ & ~0x00000200);
|
||||
} else {
|
||||
ensureAccountPathIsMutable();
|
||||
accountPath_.addAll(other.accountPath_);
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
}
|
||||
@ -4275,6 +4398,100 @@ public final class Protos {
|
||||
return encryptedDeterministicSeedBuilder_;
|
||||
}
|
||||
|
||||
private java.util.List<java.lang.Integer> accountPath_ = java.util.Collections.emptyList();
|
||||
private void ensureAccountPathIsMutable() {
|
||||
if (!((bitField0_ & 0x00000200) == 0x00000200)) {
|
||||
accountPath_ = new java.util.ArrayList<java.lang.Integer>(accountPath_);
|
||||
bitField0_ |= 0x00000200;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public java.util.List<java.lang.Integer>
|
||||
getAccountPathList() {
|
||||
return java.util.Collections.unmodifiableList(accountPath_);
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public int getAccountPathCount() {
|
||||
return accountPath_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public int getAccountPath(int index) {
|
||||
return accountPath_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder setAccountPath(
|
||||
int index, int value) {
|
||||
ensureAccountPathIsMutable();
|
||||
accountPath_.set(index, value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder addAccountPath(int value) {
|
||||
ensureAccountPathIsMutable();
|
||||
accountPath_.add(value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder addAllAccountPath(
|
||||
java.lang.Iterable<? extends java.lang.Integer> values) {
|
||||
ensureAccountPathIsMutable();
|
||||
com.google.protobuf.AbstractMessageLite.Builder.addAll(
|
||||
values, accountPath_);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated uint32 account_path = 10 [packed = true];</code>
|
||||
*
|
||||
* <pre>
|
||||
* The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder clearAccountPath() {
|
||||
accountPath_ = java.util.Collections.emptyList();
|
||||
bitField0_ = (bitField0_ & ~0x00000200);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:wallet.Key)
|
||||
}
|
||||
|
||||
@ -19003,78 +19220,79 @@ public final class Protos {
|
||||
"ode\030\001 \002(\014\022\014\n\004path\030\002 \003(\r\022\026\n\016issued_subkey" +
|
||||
"s\030\003 \001(\r\022\026\n\016lookahead_size\030\004 \001(\r\022\023\n\013isFol" +
|
||||
"lowing\030\005 \001(\010\022\036\n\023sigsRequiredToSpend\030\006 \001(" +
|
||||
"\r:\0011\"\232\003\n\003Key\022\036\n\004type\030\001 \002(\0162\020.wallet.Key." +
|
||||
"\r:\0011\"\264\003\n\003Key\022\036\n\004type\030\001 \002(\0162\020.wallet.Key." +
|
||||
"Type\022\024\n\014secret_bytes\030\002 \001(\014\022-\n\016encrypted_",
|
||||
"data\030\006 \001(\0132\025.wallet.EncryptedData\022\022\n\npub" +
|
||||
"lic_key\030\003 \001(\014\022\r\n\005label\030\004 \001(\t\022\032\n\022creation" +
|
||||
"_timestamp\030\005 \001(\003\0223\n\021deterministic_key\030\007 " +
|
||||
"\001(\0132\030.wallet.DeterministicKey\022\032\n\022determi" +
|
||||
"nistic_seed\030\010 \001(\014\022;\n\034encrypted_determini" +
|
||||
"stic_seed\030\t \001(\0132\025.wallet.EncryptedData\"a" +
|
||||
"\n\004Type\022\014\n\010ORIGINAL\020\001\022\030\n\024ENCRYPTED_SCRYPT" +
|
||||
"_AES\020\002\022\032\n\026DETERMINISTIC_MNEMONIC\020\003\022\025\n\021DE" +
|
||||
"TERMINISTIC_KEY\020\004\"5\n\006Script\022\017\n\007program\030\001" +
|
||||
" \002(\014\022\032\n\022creation_timestamp\030\002 \002(\003\"\222\001\n\020Tra",
|
||||
"nsactionInput\022\"\n\032transaction_out_point_h" +
|
||||
"ash\030\001 \002(\014\022#\n\033transaction_out_point_index" +
|
||||
"\030\002 \002(\r\022\024\n\014script_bytes\030\003 \002(\014\022\020\n\010sequence" +
|
||||
"\030\004 \001(\r\022\r\n\005value\030\005 \001(\003\"\177\n\021TransactionOutp" +
|
||||
"ut\022\r\n\005value\030\001 \002(\003\022\024\n\014script_bytes\030\002 \002(\014\022" +
|
||||
"!\n\031spent_by_transaction_hash\030\003 \001(\014\022\"\n\032sp" +
|
||||
"ent_by_transaction_index\030\004 \001(\005\"\267\003\n\025Trans" +
|
||||
"actionConfidence\0220\n\004type\030\001 \001(\0162\".wallet." +
|
||||
"TransactionConfidence.Type\022\032\n\022appeared_a" +
|
||||
"t_height\030\002 \001(\005\022\036\n\026overriding_transaction",
|
||||
"\030\003 \001(\014\022\r\n\005depth\030\004 \001(\005\022)\n\014broadcast_by\030\006 " +
|
||||
"\003(\0132\023.wallet.PeerAddress\022\033\n\023last_broadca" +
|
||||
"sted_at\030\010 \001(\003\0224\n\006source\030\007 \001(\0162$.wallet.T" +
|
||||
"ransactionConfidence.Source\"`\n\004Type\022\013\n\007U" +
|
||||
"NKNOWN\020\000\022\014\n\010BUILDING\020\001\022\013\n\007PENDING\020\002\022\025\n\021N" +
|
||||
"OT_IN_BEST_CHAIN\020\003\022\010\n\004DEAD\020\004\022\017\n\013IN_CONFL" +
|
||||
"ICT\020\005\"A\n\006Source\022\022\n\016SOURCE_UNKNOWN\020\000\022\022\n\016S" +
|
||||
"OURCE_NETWORK\020\001\022\017\n\013SOURCE_SELF\020\002\"\303\005\n\013Tra" +
|
||||
"nsaction\022\017\n\007version\030\001 \002(\005\022\014\n\004hash\030\002 \002(\014\022" +
|
||||
"&\n\004pool\030\003 \001(\0162\030.wallet.Transaction.Pool\022",
|
||||
"\021\n\tlock_time\030\004 \001(\r\022\022\n\nupdated_at\030\005 \001(\003\0223" +
|
||||
"\n\021transaction_input\030\006 \003(\0132\030.wallet.Trans" +
|
||||
"actionInput\0225\n\022transaction_output\030\007 \003(\0132" +
|
||||
"\031.wallet.TransactionOutput\022\022\n\nblock_hash" +
|
||||
"\030\010 \003(\014\022 \n\030block_relativity_offsets\030\013 \003(\005" +
|
||||
"\0221\n\nconfidence\030\t \001(\0132\035.wallet.Transactio" +
|
||||
"nConfidence\0225\n\007purpose\030\n \001(\0162\033.wallet.Tr" +
|
||||
"ansaction.Purpose:\007UNKNOWN\022+\n\rexchange_r" +
|
||||
"ate\030\014 \001(\0132\024.wallet.ExchangeRate\022\014\n\004memo\030" +
|
||||
"\r \001(\t\"Y\n\004Pool\022\013\n\007UNSPENT\020\004\022\t\n\005SPENT\020\005\022\014\n",
|
||||
"\010INACTIVE\020\002\022\010\n\004DEAD\020\n\022\013\n\007PENDING\020\020\022\024\n\020PE" +
|
||||
"NDING_INACTIVE\020\022\"\243\001\n\007Purpose\022\013\n\007UNKNOWN\020" +
|
||||
"\000\022\020\n\014USER_PAYMENT\020\001\022\020\n\014KEY_ROTATION\020\002\022\034\n" +
|
||||
"\030ASSURANCE_CONTRACT_CLAIM\020\003\022\035\n\031ASSURANCE" +
|
||||
"_CONTRACT_PLEDGE\020\004\022\033\n\027ASSURANCE_CONTRACT" +
|
||||
"_STUB\020\005\022\r\n\tRAISE_FEE\020\006\"N\n\020ScryptParamete" +
|
||||
"rs\022\014\n\004salt\030\001 \002(\014\022\020\n\001n\030\002 \001(\003:\00516384\022\014\n\001r\030" +
|
||||
"\003 \001(\005:\0018\022\014\n\001p\030\004 \001(\005:\0011\"8\n\tExtension\022\n\n\002i" +
|
||||
"d\030\001 \002(\t\022\014\n\004data\030\002 \002(\014\022\021\n\tmandatory\030\003 \002(\010" +
|
||||
"\" \n\003Tag\022\013\n\003tag\030\001 \002(\t\022\014\n\004data\030\002 \002(\014\"5\n\021Tr",
|
||||
"ansactionSigner\022\022\n\nclass_name\030\001 \002(\t\022\014\n\004d" +
|
||||
"ata\030\002 \001(\014\"\351\004\n\006Wallet\022\032\n\022network_identifi" +
|
||||
"er\030\001 \002(\t\022\034\n\024last_seen_block_hash\030\002 \001(\014\022\036" +
|
||||
"\n\026last_seen_block_height\030\014 \001(\r\022!\n\031last_s" +
|
||||
"een_block_time_secs\030\016 \001(\003\022\030\n\003key\030\003 \003(\0132\013" +
|
||||
".wallet.Key\022(\n\013transaction\030\004 \003(\0132\023.walle" +
|
||||
"t.Transaction\022&\n\016watched_script\030\017 \003(\0132\016." +
|
||||
"wallet.Script\022C\n\017encryption_type\030\005 \001(\0162\035" +
|
||||
".wallet.Wallet.EncryptionType:\013UNENCRYPT" +
|
||||
"ED\0227\n\025encryption_parameters\030\006 \001(\0132\030.wall",
|
||||
"et.ScryptParameters\022\022\n\007version\030\007 \001(\005:\0011\022" +
|
||||
"$\n\textension\030\n \003(\0132\021.wallet.Extension\022\023\n" +
|
||||
"\013description\030\013 \001(\t\022\031\n\021key_rotation_time\030" +
|
||||
"\r \001(\004\022\031\n\004tags\030\020 \003(\0132\013.wallet.Tag\0226\n\023tran" +
|
||||
"saction_signers\030\021 \003(\0132\031.wallet.Transacti" +
|
||||
"onSigner\";\n\016EncryptionType\022\017\n\013UNENCRYPTE" +
|
||||
"D\020\001\022\030\n\024ENCRYPTED_SCRYPT_AES\020\002\"R\n\014Exchang" +
|
||||
"eRate\022\022\n\ncoin_value\030\001 \002(\003\022\022\n\nfiat_value\030" +
|
||||
"\002 \002(\003\022\032\n\022fiat_currency_code\030\003 \002(\tB\035\n\023org" +
|
||||
".bitcoinj.walletB\006Protos"
|
||||
"stic_seed\030\t \001(\0132\025.wallet.EncryptedData\022\030" +
|
||||
"\n\014account_path\030\n \003(\rB\002\020\001\"a\n\004Type\022\014\n\010ORIG" +
|
||||
"INAL\020\001\022\030\n\024ENCRYPTED_SCRYPT_AES\020\002\022\032\n\026DETE" +
|
||||
"RMINISTIC_MNEMONIC\020\003\022\025\n\021DETERMINISTIC_KE" +
|
||||
"Y\020\004\"5\n\006Script\022\017\n\007program\030\001 \002(\014\022\032\n\022creati",
|
||||
"on_timestamp\030\002 \002(\003\"\222\001\n\020TransactionInput\022" +
|
||||
"\"\n\032transaction_out_point_hash\030\001 \002(\014\022#\n\033t" +
|
||||
"ransaction_out_point_index\030\002 \002(\r\022\024\n\014scri" +
|
||||
"pt_bytes\030\003 \002(\014\022\020\n\010sequence\030\004 \001(\r\022\r\n\005valu" +
|
||||
"e\030\005 \001(\003\"\177\n\021TransactionOutput\022\r\n\005value\030\001 " +
|
||||
"\002(\003\022\024\n\014script_bytes\030\002 \002(\014\022!\n\031spent_by_tr" +
|
||||
"ansaction_hash\030\003 \001(\014\022\"\n\032spent_by_transac" +
|
||||
"tion_index\030\004 \001(\005\"\267\003\n\025TransactionConfiden" +
|
||||
"ce\0220\n\004type\030\001 \001(\0162\".wallet.TransactionCon" +
|
||||
"fidence.Type\022\032\n\022appeared_at_height\030\002 \001(\005",
|
||||
"\022\036\n\026overriding_transaction\030\003 \001(\014\022\r\n\005dept" +
|
||||
"h\030\004 \001(\005\022)\n\014broadcast_by\030\006 \003(\0132\023.wallet.P" +
|
||||
"eerAddress\022\033\n\023last_broadcasted_at\030\010 \001(\003\022" +
|
||||
"4\n\006source\030\007 \001(\0162$.wallet.TransactionConf" +
|
||||
"idence.Source\"`\n\004Type\022\013\n\007UNKNOWN\020\000\022\014\n\010BU" +
|
||||
"ILDING\020\001\022\013\n\007PENDING\020\002\022\025\n\021NOT_IN_BEST_CHA" +
|
||||
"IN\020\003\022\010\n\004DEAD\020\004\022\017\n\013IN_CONFLICT\020\005\"A\n\006Sourc" +
|
||||
"e\022\022\n\016SOURCE_UNKNOWN\020\000\022\022\n\016SOURCE_NETWORK\020" +
|
||||
"\001\022\017\n\013SOURCE_SELF\020\002\"\303\005\n\013Transaction\022\017\n\007ve" +
|
||||
"rsion\030\001 \002(\005\022\014\n\004hash\030\002 \002(\014\022&\n\004pool\030\003 \001(\0162",
|
||||
"\030.wallet.Transaction.Pool\022\021\n\tlock_time\030\004" +
|
||||
" \001(\r\022\022\n\nupdated_at\030\005 \001(\003\0223\n\021transaction_" +
|
||||
"input\030\006 \003(\0132\030.wallet.TransactionInput\0225\n" +
|
||||
"\022transaction_output\030\007 \003(\0132\031.wallet.Trans" +
|
||||
"actionOutput\022\022\n\nblock_hash\030\010 \003(\014\022 \n\030bloc" +
|
||||
"k_relativity_offsets\030\013 \003(\005\0221\n\nconfidence" +
|
||||
"\030\t \001(\0132\035.wallet.TransactionConfidence\0225\n" +
|
||||
"\007purpose\030\n \001(\0162\033.wallet.Transaction.Purp" +
|
||||
"ose:\007UNKNOWN\022+\n\rexchange_rate\030\014 \001(\0132\024.wa" +
|
||||
"llet.ExchangeRate\022\014\n\004memo\030\r \001(\t\"Y\n\004Pool\022",
|
||||
"\013\n\007UNSPENT\020\004\022\t\n\005SPENT\020\005\022\014\n\010INACTIVE\020\002\022\010\n" +
|
||||
"\004DEAD\020\n\022\013\n\007PENDING\020\020\022\024\n\020PENDING_INACTIVE" +
|
||||
"\020\022\"\243\001\n\007Purpose\022\013\n\007UNKNOWN\020\000\022\020\n\014USER_PAYM" +
|
||||
"ENT\020\001\022\020\n\014KEY_ROTATION\020\002\022\034\n\030ASSURANCE_CON" +
|
||||
"TRACT_CLAIM\020\003\022\035\n\031ASSURANCE_CONTRACT_PLED" +
|
||||
"GE\020\004\022\033\n\027ASSURANCE_CONTRACT_STUB\020\005\022\r\n\tRAI" +
|
||||
"SE_FEE\020\006\"N\n\020ScryptParameters\022\014\n\004salt\030\001 \002" +
|
||||
"(\014\022\020\n\001n\030\002 \001(\003:\00516384\022\014\n\001r\030\003 \001(\005:\0018\022\014\n\001p\030" +
|
||||
"\004 \001(\005:\0011\"8\n\tExtension\022\n\n\002id\030\001 \002(\t\022\014\n\004dat" +
|
||||
"a\030\002 \002(\014\022\021\n\tmandatory\030\003 \002(\010\" \n\003Tag\022\013\n\003tag",
|
||||
"\030\001 \002(\t\022\014\n\004data\030\002 \002(\014\"5\n\021TransactionSigne" +
|
||||
"r\022\022\n\nclass_name\030\001 \002(\t\022\014\n\004data\030\002 \001(\014\"\351\004\n\006" +
|
||||
"Wallet\022\032\n\022network_identifier\030\001 \002(\t\022\034\n\024la" +
|
||||
"st_seen_block_hash\030\002 \001(\014\022\036\n\026last_seen_bl" +
|
||||
"ock_height\030\014 \001(\r\022!\n\031last_seen_block_time" +
|
||||
"_secs\030\016 \001(\003\022\030\n\003key\030\003 \003(\0132\013.wallet.Key\022(\n" +
|
||||
"\013transaction\030\004 \003(\0132\023.wallet.Transaction\022" +
|
||||
"&\n\016watched_script\030\017 \003(\0132\016.wallet.Script\022" +
|
||||
"C\n\017encryption_type\030\005 \001(\0162\035.wallet.Wallet" +
|
||||
".EncryptionType:\013UNENCRYPTED\0227\n\025encrypti",
|
||||
"on_parameters\030\006 \001(\0132\030.wallet.ScryptParam" +
|
||||
"eters\022\022\n\007version\030\007 \001(\005:\0011\022$\n\textension\030\n" +
|
||||
" \003(\0132\021.wallet.Extension\022\023\n\013description\030\013" +
|
||||
" \001(\t\022\031\n\021key_rotation_time\030\r \001(\004\022\031\n\004tags\030" +
|
||||
"\020 \003(\0132\013.wallet.Tag\0226\n\023transaction_signer" +
|
||||
"s\030\021 \003(\0132\031.wallet.TransactionSigner\";\n\016En" +
|
||||
"cryptionType\022\017\n\013UNENCRYPTED\020\001\022\030\n\024ENCRYPT" +
|
||||
"ED_SCRYPT_AES\020\002\"R\n\014ExchangeRate\022\022\n\ncoin_" +
|
||||
"value\030\001 \002(\003\022\022\n\nfiat_value\030\002 \002(\003\022\032\n\022fiat_" +
|
||||
"currency_code\030\003 \002(\tB\035\n\023org.bitcoinj.wall",
|
||||
"etB\006Protos"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
@ -19111,7 +19329,7 @@ public final class Protos {
|
||||
internal_static_wallet_Key_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_wallet_Key_descriptor,
|
||||
new java.lang.String[] { "Type", "SecretBytes", "EncryptedData", "PublicKey", "Label", "CreationTimestamp", "DeterministicKey", "DeterministicSeed", "EncryptedDeterministicSeed", });
|
||||
new java.lang.String[] { "Type", "SecretBytes", "EncryptedData", "PublicKey", "Label", "CreationTimestamp", "DeterministicKey", "DeterministicSeed", "EncryptedDeterministicSeed", "AccountPath", });
|
||||
internal_static_wallet_Script_descriptor =
|
||||
getDescriptor().getMessageTypes().get(4);
|
||||
internal_static_wallet_Script_fieldAccessorTable = new
|
||||
|
@ -266,10 +266,26 @@ public class Wallet extends BaseTaggableObject
|
||||
this(context, new KeyChainGroup(context.getParams()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param params network parameters
|
||||
* @param seed deterministic seed
|
||||
* @return a wallet from a deterministic seed with a
|
||||
* {@link org.bitcoinj.wallet.DeterministicKeyChain#ACCOUNT_ZERO_PATH 0 hardened path}
|
||||
*/
|
||||
public static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed) {
|
||||
return new Wallet(params, new KeyChainGroup(params, seed));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param params network parameters
|
||||
* @param seed deterministic seed
|
||||
* @param accountPath account path
|
||||
* @return an instance of a wallet from a deterministic seed.
|
||||
*/
|
||||
public static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
|
||||
return new Wallet(params, new KeyChainGroup(params, seed, accountPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key. A
|
||||
* watching key corresponds to account zero in the recommended BIP32 key hierarchy.
|
||||
@ -278,6 +294,13 @@ public class Wallet extends BaseTaggableObject
|
||||
return new Wallet(params, new KeyChainGroup(params, watchKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key. The account path is specified.
|
||||
*/
|
||||
public static Wallet fromWatchingKey(NetworkParameters params, DeterministicKey watchKey, ImmutableList<ChildNumber> accountPath) {
|
||||
return new Wallet(params, new KeyChainGroup(params, watchKey, accountPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key. A
|
||||
* watching key corresponds to account zero in the recommended BIP32 key hierarchy. The key is specified in base58
|
||||
@ -290,6 +313,18 @@ public class Wallet extends BaseTaggableObject
|
||||
return fromWatchingKey(params, watchKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key. The
|
||||
* account path is specified. The key is specified in base58 notation and the creation time of the key. If you don't
|
||||
* know the creation time, you can pass {@link DeterministicHierarchy#BIP32_STANDARDISATION_TIME_SECS}.
|
||||
*/
|
||||
public static Wallet fromWatchingKeyB58(NetworkParameters params, String watchKeyB58, long creationTimeSeconds,
|
||||
ImmutableList<ChildNumber> accountPath) {
|
||||
final DeterministicKey watchKey = DeterministicKey.deserializeB58(null, watchKeyB58, params);
|
||||
watchKey.setCreationTimeSeconds(creationTimeSeconds);
|
||||
return fromWatchingKey(params, watchKey, accountPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet containing a given set of keys. All further keys will be derived from the oldest key.
|
||||
*/
|
||||
|
@ -39,6 +39,7 @@ import static org.junit.Assert.*;
|
||||
|
||||
public class DeterministicKeyChainTest {
|
||||
private DeterministicKeyChain chain;
|
||||
private DeterministicKeyChain bip44chain;
|
||||
private final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes());
|
||||
|
||||
@Before
|
||||
@ -50,6 +51,11 @@ public class DeterministicKeyChainTest {
|
||||
chain = new DeterministicKeyChain(ENTROPY, "", secs);
|
||||
chain.setLookaheadSize(10);
|
||||
assertEquals(secs, checkNotNull(chain.getSeed()).getCreationTimeSeconds());
|
||||
|
||||
bip44chain = new DeterministicKeyChain(new DeterministicSeed(ENTROPY, "", secs),
|
||||
ImmutableList.of(new ChildNumber(44, true), new ChildNumber(1, true), ChildNumber.ZERO_HARDENED));
|
||||
bip44chain.setLookaheadSize(10);
|
||||
assertEquals(secs, checkNotNull(bip44chain.getSeed()).getCreationTimeSeconds());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -131,6 +137,12 @@ public class DeterministicKeyChainTest {
|
||||
|
||||
List<Protos.Key> keys = chain1.serializeToProtobuf();
|
||||
KeyChainFactory factory = new KeyChainFactory() {
|
||||
@Override
|
||||
public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed,
|
||||
KeyCrypter crypter, boolean isMarried, ImmutableList<ChildNumber> accountPath) {
|
||||
return new AccountOneChain(crypter, seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried) {
|
||||
return new AccountOneChain(crypter, seed);
|
||||
@ -248,6 +260,43 @@ public class DeterministicKeyChainTest {
|
||||
assertEquals(oldLookaheadSize, chain.getLookaheadSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializeUnencryptedBIP44() throws UnreadableWalletException {
|
||||
bip44chain.maybeLookAhead();
|
||||
DeterministicKey key1 = bip44chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||
DeterministicKey key2 = bip44chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||
DeterministicKey key3 = bip44chain.getKey(KeyChain.KeyPurpose.CHANGE);
|
||||
List<Protos.Key> keys = bip44chain.serializeToProtobuf();
|
||||
// 1 mnemonic/seed, 1 master key, 1 account key, 2 internal keys, 3 derived, 20 lookahead and 5 lookahead
|
||||
// threshold.
|
||||
int numItems = 3 // mnemonic/seed
|
||||
+ 1 // master key
|
||||
+ 1 // account key
|
||||
+ 2 // ext/int parent keys
|
||||
+ (bip44chain.getLookaheadSize() + bip44chain.getLookaheadThreshold()) * 2 // lookahead zone on each chain
|
||||
;
|
||||
assertEquals(numItems, keys.size());
|
||||
|
||||
// Get another key that will be lost during round-tripping, to ensure we can derive it again.
|
||||
DeterministicKey key4 = bip44chain.getKey(KeyChain.KeyPurpose.CHANGE);
|
||||
|
||||
final String EXPECTED_SERIALIZATION = checkSerialization(keys, "deterministic-wallet-bip44-serialization.txt");
|
||||
|
||||
// Round trip the data back and forth to check it is preserved.
|
||||
int oldLookaheadSize = bip44chain.getLookaheadSize();
|
||||
bip44chain = DeterministicKeyChain.fromProtobuf(keys, null).get(0);
|
||||
assertEquals(EXPECTED_SERIALIZATION, protoToString(bip44chain.serializeToProtobuf()));
|
||||
assertEquals(key1, bip44chain.findKeyFromPubHash(key1.getPubKeyHash()));
|
||||
assertEquals(key2, bip44chain.findKeyFromPubHash(key2.getPubKeyHash()));
|
||||
assertEquals(key3, bip44chain.findKeyFromPubHash(key3.getPubKeyHash()));
|
||||
assertEquals(key4, bip44chain.getKey(KeyChain.KeyPurpose.CHANGE));
|
||||
key1.sign(Sha256Hash.ZERO_HASH);
|
||||
key2.sign(Sha256Hash.ZERO_HASH);
|
||||
key3.sign(Sha256Hash.ZERO_HASH);
|
||||
key4.sign(Sha256Hash.ZERO_HASH);
|
||||
assertEquals(oldLookaheadSize, bip44chain.getLookaheadSize());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void notEncrypted() {
|
||||
chain.toDecrypted("fail");
|
||||
|
@ -0,0 +1,356 @@
|
||||
type: DETERMINISTIC_MNEMONIC
|
||||
secret_bytes: "aerobic toe save section draw warm cute upon raccoon mother priority pilot taste sweet next traffic fatal sword dentist original crisp team caution rebel"
|
||||
creation_timestamp: 1389353062000
|
||||
deterministic_seed: "E\032\356\206\230,\275\263\364=\334^f\307\037\350\321X7R\262z\205\3564\371tp\2639R\342\027 J\266\253\250\320\022\031\233\271~O$\330\260\214\fz\231tI\353\215*\037\355\205\213.\224?"
|
||||
account_path: 2147483692
|
||||
account_path: 2147483649
|
||||
account_path: 2147483648
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\270E0\202(\362b\023\276\264\347\226E2\360\221\347\325\233L\203\3276\272\213\2436&\304\373\221\025"
|
||||
public_key: "\002\342$\253\332\031\352\324q\316M\251}\274\267\370X$\366>Q\316\005\330\376\353f!WHLL\a"
|
||||
creation_timestamp: 1389353062000
|
||||
deterministic_key {
|
||||
chain_code: "XL\240FW\203\316\230\334\374J\003\357=\215\001\206\365\207Z\006m\334X`\236,;_\304\000^"
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\370\\\267\361L\021K\214\215\272yRP\234(\304\365\303h\251\250\0236\270\344\210\300\330\363(=\332"
|
||||
public_key: "\002\026n\227\337\232\000\032Q\204\374o-o\277\367;\027.\312Z\024\353\271\300\353j5\375O\270W\266"
|
||||
deterministic_key {
|
||||
chain_code: "\367vcS\210\365\365\302\353\321\240\307\327\203\350H\334E\336 \236\037\256\265pT\235\035\221\235\"~"
|
||||
path: 2147483692
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\274\244m\336\241`\024\301;Y\024m)\245\375\212\261B\005TnE\217\r \315\323\322\354w\227\225"
|
||||
public_key: "\003\243q\304\333\310{\001\317\250\266\264\250\353\271\217\r\322l\274M\235\306\347\224\nax\023\334\273\226\321"
|
||||
deterministic_key {
|
||||
chain_code: "\344\021F\354\025\3341T\233\'\276&Q\324\325w\362\362n\004\320\210)\033\023\303\244T\371\331\373f"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\023\354\032\244\374<y\254aq\a\362=\345\204\n^;5\213M\267\311\234\037RkX\235\363ae"
|
||||
public_key: "\002T5VO\274\362m\300\320\352\005\r!\307\024\250\307C\324\323\215[\232@\254S\270\217\362\370\214\362"
|
||||
deterministic_key {
|
||||
chain_code: "F\336\2067\377M\026)%\357ZL#\203\320\324\217-\3305\310\244\n\205\277E\323L\250ww\314"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\362\305\242\3637\2748Z?]\035s\272\253J\300\033\250\022r\350\020\277U\036K<\335\237\333/\303"
|
||||
public_key: "\003\2471\326i\331A\337|\373\276\3214\257\363\266Q\315x\341\317\200\243\234\336<s}\261\240,\233\371"
|
||||
deterministic_key {
|
||||
chain_code: "Pd\032#\325\213\332\307\3755\020\316\276\002\037\262\241\213\211k\376\254\220R\351\270\"\260V\260\362\257"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
issued_subkeys: 2
|
||||
lookahead_size: 10
|
||||
sigsRequiredToSpend: 1
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\311\327\205Q\005\346\030\365\026\0331\356\346\036\234\024\b\322\202\3726I\351\001 \373\200\003\260\276\216\000"
|
||||
public_key: "\003\334\214L\003Zq\365\212P\203b~l\367C@T\341\300\216\037\375\002\224\t=\301:\266l\364"
|
||||
deterministic_key {
|
||||
chain_code: "\036\277^\322!\227i^Z\212\347\272\365C\016\342\371\236a\022\\\n\037\304\264\021\335\344\340=\234T"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
issued_subkeys: 1
|
||||
lookahead_size: 10
|
||||
sigsRequiredToSpend: 1
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\232\236W\2235py\021\331i\350\026H\235\nO\217\231\361M/}5\211v\023Kc\253\2307"
|
||||
deterministic_key {
|
||||
chain_code: "\032\366\331\360\276Yo\243;!\023\005\305\246\354\337N\203\302\264\250\355\275\346\271!L\\\252\270\364t"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 0
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\231\254]q\030g3\316u\322h\304Ao4\246f\026\266\374\nY\233\022\034\243\'\000\030\256\342\006"
|
||||
deterministic_key {
|
||||
chain_code: "\364\201U66\201$7l%Sy\365]A\265\277&\370\256\364\347\356\334T\323\375\347mB0\374"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 1
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002/ \336M\347\357pl@z\204\3240\027\366\0170\307\337\327\312_$\n\'\216\237W\017\263bg"
|
||||
deterministic_key {
|
||||
chain_code: "i\206:\003\205BLMI\376\347S~\315\0306\255\274>\220\017\302\241u\017DvD\2662\342\316"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 2
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003 1\316\277\355_\343\214}\a\205\233\325\232\241n\256\325\300\2369\020\nh\335\0243\355\362$?7"
|
||||
deterministic_key {
|
||||
chain_code: "\334(\\u\022\245\370\t*\372\315\330\365\256Ms\254J_{B\035[f\333\351\272\261\363\373_\023"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 3
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\354\fhI\2731\026\222\v\274\027\357\327\033X\324\270\323\252}\314}\221\213\272\\\362k\352\334#"
|
||||
deterministic_key {
|
||||
chain_code: "#\351\"(\t\245\006\351\354f\334\216(\272\252\200\226\337\370\260XO\375\016/\377\306\263yE\222\311"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 4
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002-7\rx2zP\r(B\247\350\026\205\210w\251G\b\254\213\000\227\271Q\272\342\357\304>G"
|
||||
deterministic_key {
|
||||
chain_code: "US\242J\307\2672<\373l\217\200[\316\352\361*~\324\f\304\267oD\273\300_\340K\247V\370"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 5
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002Y\260\332\377;T\263\335\331\004\020kv\207E=\311|\270*hP>)\340\272\203LD\036\313\271"
|
||||
deterministic_key {
|
||||
chain_code: "\r34\'I\027\266\272\300\003\366f\274\333\260\006\311\3556!\227\216\301\361\247\354\025\305\321\376\274\214"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 6
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002I\367x\235p9\334\234\034\366\247&\321\237\217\241V\252\017`w\212\301\000\305-\312\003\352`\302V"
|
||||
deterministic_key {
|
||||
chain_code: "\257\001\375\203E\315\221W\316&\035\244\306\037\351\361\027\020\346\305^Z\274O\212\363P\036\273n\367\326"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 7
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\0029\373\030u\305\214S\345/\373y%\t\252~\267\f\016t|\354\020\356\306\313\317\027\325\376\232kh"
|
||||
deterministic_key {
|
||||
chain_code: "\260\203\277\231\352\265y\020\356r_bO\374l\347\002\032i\216Ct\260\221-\207\200\243\364;\247I"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 8
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002[\304\301.\342\253\256\364\025\'\017\356-t\340R\250Z\327\374\250\r\331\221`\334\362a[q\260\271"
|
||||
deterministic_key {
|
||||
chain_code: "\376\277#\275\035S\362`\323\246<b~D\253\250p\263\256\364\257\256\201\016\223[\305\261\2758\353\203"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 9
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\253\213j!\316\\\372-tA\331\362T\363\252)\302\2620\246=X#\201\274\212\331Gi9\362\366"
|
||||
deterministic_key {
|
||||
chain_code: "S`\237\003Q\021\201\301\341Ij\"\270:\335\374;\320\037\350m\037\331\343\3208\211E\276y\215."
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 10
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\231\323\307\3348\267\357\310\323\nWf$\326\334\v\360\273\357\207\0207\036)\270Api\346\321\270\351"
|
||||
deterministic_key {
|
||||
chain_code: "\232Y6\020\317@\r\251]\204m\37796\v5\006\300\t\342\246.\231r\336Vt\370\373\023_M"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 11
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\3647\fs\313\367\022\317\207\276\305\370W\b \276\274\343\344r\351\303\035\235\227X\a\347Q2\325\351"
|
||||
deterministic_key {
|
||||
chain_code: "\030F|\234$0\315\215\203\234\037\0054\344M\253\343\214S\360\274_\330\2663\364L\025\250\v\236\247"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 0
|
||||
path: 12
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\273\t\2539\246\023^H\232\202}Hi+\226Q\337\371\002\021\201\276\261*\236\353\'\247\325\367t^"
|
||||
deterministic_key {
|
||||
chain_code: "\233\314\253j\213|Y\344\200k\217\357*\\\030\347`\016\266\033g|\273\330\261\226cj\204\351\234Z"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 0
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\266}M\017f0\350\357\232\037\2713\203N\nei\202_\t\034\0343X,\006Y\260\356\340\031W"
|
||||
deterministic_key {
|
||||
chain_code: "\2569jU\231\242\230rH\202\025\356C\373\327\374-\305\313\277Jy5mx\034\350\2264\321\327J"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 1
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\221o\254\027\3547s\260&\217b\252r\fo)~\2107\016\255\273\223\245A\234\247ay\204\021H"
|
||||
deterministic_key {
|
||||
chain_code: "\265\233\233\354DG\226\326\215\024\230\334\262J\257LL\363R\316$\357\347\017v\371rpA\244PK"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 2
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\301\036A\004O\323\350\240\227>C73n\326P]{\260@\327\242\'\263$H\271\371\371YIJ"
|
||||
deterministic_key {
|
||||
chain_code: "9\214\315\275\300\206\253U;\235\002fA\016\215\222\235K\253\311\3648w20\2005\343\310\\:"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 3
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002!\373+L\341\025\265\232\a\247J?v\274\273|v\035g\033\211\026\332\233\37378c\226\020\304\360"
|
||||
deterministic_key {
|
||||
chain_code: "i\003w\037b!Y]\214l\373]`x\355Je\\\v\205\n\310\254s\301\272\246\315\024}\366\037"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 4
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002p\261|\230%\350\a\347?-}\317\274W\210\032\331\006\350\320\016\331\300\024\302\321[O\210E\231\342"
|
||||
deterministic_key {
|
||||
chain_code: "\367\263\236B#W\223\3206\3644!?Im\250\277\vY\322\302\254\212A\227\352\244\003\031)\374b"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 5
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\355\213b\333\3157\262iu\361\274\252\271\223\346\276^\350\260q\272m\025.\256\353\006\005\020\255&\017"
|
||||
deterministic_key {
|
||||
chain_code: "\003\265\376U\001\240P\'X\364\326\326\275\375s\306\225\373\264\306H5[\356\b\301>\227\325\323\315\344"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 6
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\003\317\215\311\246\322\335\226,\355\243\274E\270\027\307I\264\344\260\350_\230\372\034\340\363\3113T\222\274c"
|
||||
deterministic_key {
|
||||
chain_code: "r\203\252\217hI\312S\323\377](\331C\2711\214T.\031\277\333\267,U|\323x\006\003\263\233"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 7
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\277\306\215\221N\224\b=\v\001\216Ui\033v\250\326\361\221\332\215\343$\344A\306\357f\236\330\241\337"
|
||||
deterministic_key {
|
||||
chain_code: "1n@\331(\246#4\262\017\006\360a\206i\270\211n\344\363\343Y\0000\372,\231\352\252f\272!"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 8
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002!\032\210\034\267\234\t\311T\'(~c-dKt;\366\030fI5[\026\242\372\310\342\'\205"
|
||||
deterministic_key {
|
||||
chain_code: "\004AX{\301\030\035K\353\353S\223m\271\352\323\272\'\202=_5\322\240J.\227\370[gZ?"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 9
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002KZ\215?\f\365\"o\364\035\n\240\276_\335\\\256\277\212J\247\201A\325\220\361\356\213/!\301\224"
|
||||
deterministic_key {
|
||||
chain_code: "\247\233H)F\252\276\242\370\350\263\270\b:^\247d]\232\316QUA2\n\262\321U\003\r]"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 10
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\204U\310%\024\"\363\267\340\220\031\341koQ\210\037\022\224Y\354\016\370\360\374\346\216\354@B\247\233"
|
||||
deterministic_key {
|
||||
chain_code: "w\265\277h\352\025\351\274\233\310;rk\264`*-H-r\026\326\237%\230\034\005\236_6#a"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 11
|
||||
}
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
public_key: "\002\213\241A\022c\322\031\367O\273\375\3354\'Vh\371\362\202\220\253\366\206:\033\347\300\227<6\252\034"
|
||||
deterministic_key {
|
||||
chain_code: "R\222\341\341.\352\306O\340+\276\266#K\211\022\264\203\225\240\246\263\023l\327\356 \350\342\242]F"
|
||||
path: 2147483692
|
||||
path: 2147483649
|
||||
path: 2147483648
|
||||
path: 1
|
||||
path: 12
|
||||
}
|
@ -2,6 +2,7 @@ type: DETERMINISTIC_MNEMONIC
|
||||
secret_bytes: "aerobic toe save section draw warm cute upon raccoon mother priority pilot taste sweet next traffic fatal sword dentist original crisp team caution rebel"
|
||||
creation_timestamp: 1389353062000
|
||||
deterministic_seed: "E\032\356\206\230,\275\263\364=\334^f\307\037\350\321X7R\262z\205\3564\371tp\2639R\342\027 J\266\253\250\320\022\031\233\271~O$\330\260\214\fz\231tI\353\215*\037\355\205\213.\224?"
|
||||
account_path: 2147483648
|
||||
|
||||
type: DETERMINISTIC_KEY
|
||||
secret_bytes: "\270E0\202(\362b\023\276\264\347\226E2\360\221\347\325\233L\203\3276\272\213\2436&\304\373\221\025"
|
||||
|
@ -132,6 +132,9 @@ message Key {
|
||||
|
||||
// Encrypted version of the seed
|
||||
optional EncryptedData encrypted_deterministic_seed = 9;
|
||||
|
||||
// The path to the root. Only applicable to a DETERMINISTIC_MNEMONIC key entry.
|
||||
repeated uint32 account_path = 10 [packed = true];
|
||||
}
|
||||
|
||||
message Script {
|
||||
|
Loading…
x
Reference in New Issue
Block a user