diff --git a/core/src/main/java/com/google/bitcoin/core/Wallet.java b/core/src/main/java/com/google/bitcoin/core/Wallet.java index 622a290cf..565168831 100644 --- a/core/src/main/java/com/google/bitcoin/core/Wallet.java +++ b/core/src/main/java/com/google/bitcoin/core/Wallet.java @@ -243,6 +243,11 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha this.keychain = checkNotNull(keyChainGroup); if (params == UnitTestParams.get()) this.keychain.setLookaheadSize(5); // Cut down excess computation for unit tests. + // If this keychain was created fresh just now (new wallet), make HD so a backup can be made immediately + // without having to call current/freshReceiveKey. If there are already keys in the chain of any kind then + // we're probably being deserialized so leave things alone: the API user can upgrade later. + if (this.keychain.numKeys() == 0) + this.keychain.createAndActivateNewHDChain(); watchedScripts = Sets.newHashSet(); unspent = new HashMap(); spent = new HashMap(); diff --git a/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java b/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java index c19f5a9ab..b7827ff07 100644 --- a/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java +++ b/core/src/test/java/com/google/bitcoin/core/BloomFilterTest.java @@ -18,6 +18,7 @@ package com.google.bitcoin.core; import com.google.bitcoin.params.MainNetParams; +import com.google.bitcoin.wallet.KeyChainGroup; import org.junit.Test; import java.util.Arrays; @@ -72,11 +73,11 @@ public class BloomFilterTest { Address addr = privKey.getKey().toAddress(params); assertTrue(addr.toString().equals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e")); - - Wallet wallet = new Wallet(params); - wallet.importKey(privKey.getKey()); + + KeyChainGroup group = new KeyChainGroup(params); // Add a random key which happens to have been used in a recent generation - wallet.importKey(ECKey.fromPublicOnly(HEX.decode("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99"))); + group.importKeys(privKey.getKey(), ECKey.fromPublicOnly(HEX.decode("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99"))); + Wallet wallet = new Wallet(params, group); wallet.commitTx(new Transaction(params, HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038754030114062f503253482fffffffff01c05e559500000000232103cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99ac00000000"))); // We should have 2 per pubkey, and one for the pay-2-pubkey output we have diff --git a/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkleTreeTests.java b/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkleTreeTests.java index c2c6661f0..2b9eb2bae 100644 --- a/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkleTreeTests.java +++ b/core/src/test/java/com/google/bitcoin/core/FilteredBlockAndPartialMerkleTreeTests.java @@ -22,6 +22,7 @@ import com.google.bitcoin.params.UnitTestParams; import com.google.bitcoin.store.MemoryBlockStore; import com.google.bitcoin.testing.InboundMessageQueuer; import com.google.bitcoin.testing.TestWithPeerGroup; +import com.google.bitcoin.wallet.KeyChainGroup; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -100,12 +101,13 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup { assertEquals(tx3.getHash(),txHashList.get(3)); // A wallet which contains a pubkey used in each transaction from above - Wallet wallet = new Wallet(unitTestParams); - wallet.importKey(ECKey.fromPublicOnly(HEX.decode("04b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63"))); - wallet.importKey(ECKey.fromPublicOnly(HEX.decode("04732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ec"))); - wallet.importKey(ECKey.fromPublicOnly(HEX.decode("04cfb4113b3387637131ebec76871fd2760fc430dd16de0110f0eb07bb31ffac85e2607c189cb8582ea1ccaeb64ffd655409106589778f3000fdfe3263440b0350"))); - wallet.importKey(ECKey.fromPublicOnly(HEX.decode("04b2f30018908a59e829c1534bfa5010d7ef7f79994159bba0f534d863ef9e4e973af6a8de20dc41dbea50bc622263ec8a770b2c9406599d39e4c9afe61f8b1613"))); - + KeyChainGroup group = new KeyChainGroup(unitTestParams); + group.importKeys(ECKey.fromPublicOnly(HEX.decode("04b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63")), + ECKey.fromPublicOnly(HEX.decode("04732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ec")), + ECKey.fromPublicOnly(HEX.decode("04cfb4113b3387637131ebec76871fd2760fc430dd16de0110f0eb07bb31ffac85e2607c189cb8582ea1ccaeb64ffd655409106589778f3000fdfe3263440b0350")), + ECKey.fromPublicOnly(HEX.decode("04b2f30018908a59e829c1534bfa5010d7ef7f79994159bba0f534d863ef9e4e973af6a8de20dc41dbea50bc622263ec8a770b2c9406599d39e4c9afe61f8b1613"))); + Wallet wallet = new Wallet(unitTestParams, group); + BloomFilter filter = wallet.getBloomFilter(wallet.getKeychainSize()*2, 0.001, 0xDEADBEEF); // Compare the serialized bloom filter to a known-good value assertTrue(Arrays.equals(filter.bitcoinSerialize(), HEX.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde02"))); diff --git a/core/src/test/java/com/google/bitcoin/core/WalletTest.java b/core/src/test/java/com/google/bitcoin/core/WalletTest.java index b46e11066..37a4bdf03 100644 --- a/core/src/test/java/com/google/bitcoin/core/WalletTest.java +++ b/core/src/test/java/com/google/bitcoin/core/WalletTest.java @@ -1017,32 +1017,25 @@ public class WalletTest extends TestWithWallet { @Test public void keyCreationTime() throws Exception { - wallet = new Wallet(params); Utils.setMockClock(); long now = Utils.currentTimeSeconds(); - // No keys returns current time. + wallet = new Wallet(params); assertEquals(now, wallet.getEarliestKeyCreationTime()); Utils.rollMockClock(60); wallet.freshReceiveKey(); - assertEquals(now + 60, wallet.getEarliestKeyCreationTime()); - Utils.rollMockClock(60); - wallet.freshReceiveKey(); - assertEquals(now + 60, wallet.getEarliestKeyCreationTime()); + assertEquals(now, wallet.getEarliestKeyCreationTime()); } @Test public void scriptCreationTime() throws Exception { - wallet = new Wallet(params); Utils.setMockClock(); long now = Utils.currentTimeSeconds(); - // No keys returns current time. + wallet = new Wallet(params); assertEquals(now, wallet.getEarliestKeyCreationTime()); - Utils.rollMockClock(60); + Utils.rollMockClock(-120); wallet.addWatchedAddress(new ECKey().toAddress(params)); - - Utils.rollMockClock(60); wallet.freshReceiveKey(); - assertEquals(now + 60, wallet.getEarliestKeyCreationTime()); + assertEquals(now - 120, wallet.getEarliestKeyCreationTime()); } @Test @@ -2483,9 +2476,9 @@ public class WalletTest extends TestWithWallet { // much where it goes). Wallet on the other hand will try to auto-upgrade you when possible. // Create an old-style random wallet. - wallet = new Wallet(params); - wallet.importKey(new ECKey()); - wallet.importKey(new ECKey()); + KeyChainGroup group = new KeyChainGroup(params); + group.importKeys(new ECKey(), new ECKey()); + wallet = new Wallet(params, group); assertTrue(wallet.isDeterministicUpgradeRequired()); // Use an HD feature. wallet.freshReceiveKey(); @@ -2495,9 +2488,9 @@ public class WalletTest extends TestWithWallet { @Test public void upgradeToHDEncrypted() throws Exception { // Create an old-style random wallet. - wallet = new Wallet(params); - wallet.importKey(new ECKey()); - wallet.importKey(new ECKey()); + KeyChainGroup group = new KeyChainGroup(params); + group.importKeys(new ECKey(), new ECKey()); + wallet = new Wallet(params, group); assertTrue(wallet.isDeterministicUpgradeRequired()); KeyCrypter crypter = new KeyCrypterScrypt(); KeyParameter aesKey = crypter.deriveKey("abc"); diff --git a/core/src/test/java/com/google/bitcoin/store/WalletProtobufSerializerTest.java b/core/src/test/java/com/google/bitcoin/store/WalletProtobufSerializerTest.java index dde0fb5f3..74a87a105 100644 --- a/core/src/test/java/com/google/bitcoin/store/WalletProtobufSerializerTest.java +++ b/core/src/test/java/com/google/bitcoin/store/WalletProtobufSerializerTest.java @@ -111,7 +111,7 @@ public class WalletProtobufSerializerTest { assertEquals(Protos.Key.Type.ORIGINAL, walletProto.getKey(0).getType()); assertEquals(0, walletProto.getExtensionCount()); assertEquals(1, walletProto.getTransactionCount()); - assertEquals(1, walletProto.getKeyCount()); + assertEquals(6, walletProto.getKeyCount()); Protos.Transaction t1p = walletProto.getTransaction(0); assertEquals(0, t1p.getBlockHashCount());