mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-10 09:20:04 +01:00
WalletTool: allow creation of a wallet from a given [word] seed.
This commit is contained in:
parent
1ff5d05200
commit
a1fcca3883
3 changed files with 53 additions and 18 deletions
|
@ -208,6 +208,10 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||
this(params, new KeyChainGroup());
|
||||
}
|
||||
|
||||
public static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed) {
|
||||
return new Wallet(params, new KeyChainGroup(seed));
|
||||
}
|
||||
|
||||
// TODO: When this class moves to the Wallet package, along with the protobuf serializer, then hide this.
|
||||
/** For internal use only. */
|
||||
public Wallet(NetworkParameters params, KeyChainGroup keyChainGroup) {
|
||||
|
|
|
@ -42,6 +42,9 @@ public class MnemonicCode {
|
|||
|
||||
public static String BIP39_ENGLISH_SHA256 = "ad90bf3beb7b0eb7e5acd74727dc0da96e0a280a258354e7293fb7e211ac03db";
|
||||
|
||||
/** UNIX time for when the BIP39 standard was finalised. This can be used as a default seed birthday. */
|
||||
public static long BIP39_STANDARDISATION_TIME_SECS = 1381276800;
|
||||
|
||||
private static final int PBKDF2_ROUNDS = 2048;
|
||||
|
||||
public MnemonicCode() throws IOException {
|
||||
|
|
|
@ -19,6 +19,8 @@ package com.google.bitcoin.tools;
|
|||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.bitcoin.crypto.KeyCrypterException;
|
||||
import com.google.bitcoin.crypto.MnemonicCode;
|
||||
import com.google.bitcoin.crypto.MnemonicException;
|
||||
import com.google.bitcoin.net.discovery.DnsDiscovery;
|
||||
import com.google.bitcoin.params.MainNetParams;
|
||||
import com.google.bitcoin.params.RegTestParams;
|
||||
|
@ -30,7 +32,9 @@ import com.google.bitcoin.store.*;
|
|||
import com.google.bitcoin.uri.BitcoinURI;
|
||||
import com.google.bitcoin.uri.BitcoinURIParseException;
|
||||
import com.google.bitcoin.utils.BriefLogFormatter;
|
||||
import com.google.bitcoin.wallet.DeterministicSeed;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
@ -67,12 +71,13 @@ import java.util.logging.LogManager;
|
|||
public class WalletTool {
|
||||
private static final Logger log = LoggerFactory.getLogger(WalletTool.class);
|
||||
|
||||
private static OptionSet options;
|
||||
private static OptionSpec<Date> dateFlag;
|
||||
private static OptionSpec<Integer> unixtimeFlag;
|
||||
private static OptionSpec<String> seedFlag;
|
||||
|
||||
private static NetworkParameters params;
|
||||
private static File walletFile;
|
||||
private static OptionSet options;
|
||||
private static BlockStore store;
|
||||
private static AbstractBlockChain chain;
|
||||
private static PeerGroup peers;
|
||||
|
@ -176,23 +181,13 @@ public class WalletTool {
|
|||
parser.accepts("help");
|
||||
parser.accepts("force");
|
||||
parser.accepts("debuglog");
|
||||
OptionSpec<String> walletFileName = parser.accepts("wallet")
|
||||
.withRequiredArg()
|
||||
.defaultsTo("wallet");
|
||||
OptionSpec<NetworkEnum> netFlag = parser.accepts("net")
|
||||
.withOptionalArg()
|
||||
.ofType(NetworkEnum.class)
|
||||
.defaultsTo(NetworkEnum.PROD);
|
||||
dateFlag = parser.accepts("date")
|
||||
.withRequiredArg()
|
||||
.ofType(Date.class)
|
||||
OptionSpec<String> walletFileName = parser.accepts("wallet").withRequiredArg().defaultsTo("wallet");
|
||||
seedFlag = parser.accepts("seed").withRequiredArg();
|
||||
OptionSpec<NetworkEnum> netFlag = parser.accepts("net").withOptionalArg().ofType(NetworkEnum.class).defaultsTo(NetworkEnum.PROD);
|
||||
dateFlag = parser.accepts("date").withRequiredArg().ofType(Date.class)
|
||||
.withValuesConvertedBy(DateConverter.datePattern("yyyy/MM/dd"));
|
||||
OptionSpec<WaitForEnum> waitForFlag = parser.accepts("waitfor")
|
||||
.withRequiredArg()
|
||||
.ofType(WaitForEnum.class);
|
||||
OptionSpec<ValidationMode> modeFlag = parser.accepts("mode")
|
||||
.withRequiredArg()
|
||||
.ofType(ValidationMode.class)
|
||||
OptionSpec<WaitForEnum> waitForFlag = parser.accepts("waitfor").withRequiredArg().ofType(WaitForEnum.class);
|
||||
OptionSpec<ValidationMode> modeFlag = parser.accepts("mode").withRequiredArg().ofType(ValidationMode.class)
|
||||
.defaultsTo(ValidationMode.SPV);
|
||||
OptionSpec<String> chainFlag = parser.accepts("chain").withRequiredArg();
|
||||
// For addkey/delkey.
|
||||
|
@ -798,7 +793,40 @@ public class WalletTool {
|
|||
System.err.println("Wallet creation requested but " + walletFile + " already exists, use --force");
|
||||
return;
|
||||
}
|
||||
if (options.has(seedFlag)) {
|
||||
long creationTimeSecs = MnemonicCode.BIP39_STANDARDISATION_TIME_SECS;
|
||||
if (options.has(dateFlag))
|
||||
creationTimeSecs = options.valueOf(dateFlag).getTime() / 1000;
|
||||
String seedStr = options.valueOf(seedFlag);
|
||||
DeterministicSeed seed;
|
||||
if (seedStr.contains(" ")) {
|
||||
// Parse as mnemonic code.
|
||||
final List<String> split = ImmutableList.copyOf(Splitter.on(" ").omitEmptyStrings().split(seedStr));
|
||||
try {
|
||||
seed = new DeterministicSeed(split, creationTimeSecs);
|
||||
} catch (MnemonicException.MnemonicLengthException e) {
|
||||
System.err.println("The seed did not have 12 words in, perhaps you need quotes around it?");
|
||||
return;
|
||||
} catch (MnemonicException.MnemonicWordException e) {
|
||||
System.err.println("The seed contained an unrecognised word: " + e.badWord);
|
||||
return;
|
||||
} catch (MnemonicException.MnemonicChecksumException e) {
|
||||
System.err.println("The seed did not pass checksumming, perhaps one of the words is wrong?");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Parse as hex or base58
|
||||
byte[] bits = Utils.parseAsHexOrBase58(seedStr);
|
||||
if (bits.length != 16) {
|
||||
System.err.println("The given hex/base58 string is not 16 bytes");
|
||||
return;
|
||||
}
|
||||
seed = new DeterministicSeed(bits, creationTimeSecs);
|
||||
}
|
||||
wallet = Wallet.fromSeed(params, seed);
|
||||
} else {
|
||||
wallet = new Wallet(params);
|
||||
}
|
||||
if (password != null)
|
||||
wallet.encrypt(password);
|
||||
wallet.saveToFile(walletFile);
|
||||
|
|
Loading…
Add table
Reference in a new issue