public void serializeUnencrypted(SimpleHDKeyChain keyChain, String expectedSerialization) throws UnreadableWalletException { keyChain.setLookaheadSize(10); keyChain.maybeLookAhead(); DeterministicKey key1 = keyChain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); DeterministicKey key2 = keyChain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); DeterministicKey key3 = keyChain.getKey(KeyChain.KeyPurpose.CHANGE); List<Protos.Key> keys = keyChain.toProtobuf(); // 1 master key, 1 account key, 2 internal keys, 3 derived, 20 lookahead and 5 lookahead // threshold. int numItems = 1 // master key/account key + 2 // ext/int parent keys + (keyChain.getLookaheadSize() + keyChain.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 = keyChain.getKey(KeyChain.KeyPurpose.CHANGE); String sb = protoToString(keys); assertEquals(expectedSerialization, sb); // Round trip the data back and forth to check it is preserved. int oldLookaheadSize = keyChain.getLookaheadSize(); keyChain = SimpleHDKeyChain.fromProtobuf(keys, null); assertEquals(expectedSerialization, protoToString(keyChain.toProtobuf())); assertEquals(key1, keyChain.findKeyFromPubHash(key1.getPubKeyHash())); assertEquals(key2, keyChain.findKeyFromPubHash(key2.getPubKeyHash())); assertEquals(key3, keyChain.findKeyFromPubHash(key3.getPubKeyHash())); assertEquals(key4, keyChain.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, keyChain.getLookaheadSize()); }
@Test public void events() throws Exception { // Check that we get the right events at the right time. final List<List<ECKey>> listenerKeys = Lists.newArrayList(); long secs = 1389353062L; chain.addEventListener( new AbstractKeyChainEventListener() { @Override public void onKeysAdded(List<ECKey> keys) { listenerKeys.add(keys); } }, Threading.SAME_THREAD); assertEquals(0, listenerKeys.size()); chain.setLookaheadSize(5); assertEquals(0, listenerKeys.size()); ECKey key = chain.getKey(SimpleHDKeyChain.KeyPurpose.CHANGE); assertEquals(1, listenerKeys.size()); // 1 event final List<ECKey> firstEvent = listenerKeys.get(0); assertEquals(1, firstEvent.size()); assertTrue(firstEvent.contains(key)); // order is not specified. listenerKeys.clear(); chain.maybeLookAhead(); final List<ECKey> secondEvent = listenerKeys.get(0); assertEquals(12, secondEvent.size()); // (5 lookahead keys, +1 lookahead threshold) * 2 chains listenerKeys.clear(); chain.getKey(SimpleHDKeyChain.KeyPurpose.CHANGE); // At this point we've entered the threshold zone so more keys won't immediately trigger more // generations. assertEquals(0, listenerKeys.size()); // 1 event final int lookaheadThreshold = chain.getLookaheadThreshold() + chain.getLookaheadSize(); for (int i = 0; i < lookaheadThreshold; i++) chain.getKey(SimpleHDKeyChain.KeyPurpose.CHANGE); assertEquals(1, listenerKeys.size()); // 1 event assertEquals(1, listenerKeys.get(0).size()); // 1 key. }