@Test public void testLastBlockSeenHash() throws Exception { // Test the lastBlockSeenHash field works. // LastBlockSeenHash should be empty if never set. Wallet wallet = new Wallet(params); Protos.Wallet walletProto = new WalletProtobufSerializer().walletToProto(wallet); ByteString lastSeenBlockHash = walletProto.getLastSeenBlockHash(); assertTrue(lastSeenBlockHash.isEmpty()); // Create a block. Block block = params.getDefaultSerializer().makeBlock(BlockTest.blockBytes); Sha256Hash blockHash = block.getHash(); wallet.setLastBlockSeenHash(blockHash); wallet.setLastBlockSeenHeight(1); // Roundtrip the wallet and check it has stored the blockHash. Wallet wallet1 = roundTrip(wallet); assertEquals(blockHash, wallet1.getLastBlockSeenHash()); assertEquals(1, wallet1.getLastBlockSeenHeight()); // Test the Satoshi genesis block (hash of all zeroes) is roundtripped ok. Block genesisBlock = MainNetParams.get().getGenesisBlock(); wallet.setLastBlockSeenHash(genesisBlock.getHash()); Wallet wallet2 = roundTrip(wallet); assertEquals(genesisBlock.getHash(), wallet2.getLastBlockSeenHash()); }
/** * Loads wallet data from the given protocol buffer and inserts it into the given Wallet object. * This is primarily useful when you wish to pre-register extension objects. Note that if loading * fails the provided Wallet object may be in an indeterminate state and should be thrown away. * * <p>A wallet can be unreadable for various reasons, such as inability to open the file, corrupt * data, internally inconsistent data, a wallet extension marked as mandatory that cannot be * handled and so on. You should always handle {@link UnreadableWalletException} and communicate * failure to the user in an appropriate manner. * * @throws UnreadableWalletException thrown in various error conditions (see description). */ public Wallet readWallet( NetworkParameters params, @Nullable WalletExtension[] extensions, Protos.Wallet walletProto) throws UnreadableWalletException { if (walletProto.getVersion() > 1) throw new UnreadableWalletException.FutureVersion(); if (!walletProto.getNetworkIdentifier().equals(params.getId())) throw new UnreadableWalletException.WrongNetwork(); int sigsRequiredToSpend = walletProto.getSigsRequiredToSpend(); // Read the scrypt parameters that specify how encryption and decryption is performed. KeyChainGroup chain; if (walletProto.hasEncryptionParameters()) { Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters(); final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters); chain = KeyChainGroup.fromProtobufEncrypted( params, walletProto.getKeyList(), sigsRequiredToSpend, keyCrypter); } else { chain = KeyChainGroup.fromProtobufUnencrypted( params, walletProto.getKeyList(), sigsRequiredToSpend); } Wallet wallet = factory.create(params, chain); List<Script> scripts = Lists.newArrayList(); for (Protos.Script protoScript : walletProto.getWatchedScriptList()) { try { Script script = new Script( protoScript.getProgram().toByteArray(), protoScript.getCreationTimestamp() / 1000); scripts.add(script); } catch (ScriptException e) { throw new UnreadableWalletException("Unparseable script in wallet"); } } wallet.addWatchedScripts(scripts); if (walletProto.hasDescription()) { wallet.setDescription(walletProto.getDescription()); } // Read all transactions and insert into the txMap. for (Protos.Transaction txProto : walletProto.getTransactionList()) { readTransaction(txProto, wallet.getParams()); } // Update transaction outputs to point to inputs that spend them for (Protos.Transaction txProto : walletProto.getTransactionList()) { WalletTransaction wtx = connectTransactionOutputs(txProto); wallet.addWalletTransaction(wtx); } // Update the lastBlockSeenHash. if (!walletProto.hasLastSeenBlockHash()) { wallet.setLastBlockSeenHash(null); } else { wallet.setLastBlockSeenHash(byteStringToHash(walletProto.getLastSeenBlockHash())); } if (!walletProto.hasLastSeenBlockHeight()) { wallet.setLastBlockSeenHeight(-1); } else { wallet.setLastBlockSeenHeight(walletProto.getLastSeenBlockHeight()); } // Will default to zero if not present. wallet.setLastBlockSeenTimeSecs(walletProto.getLastSeenBlockTimeSecs()); if (walletProto.hasKeyRotationTime()) { wallet.setKeyRotationTime(new Date(walletProto.getKeyRotationTime() * 1000)); } loadExtensions(wallet, extensions != null ? extensions : new WalletExtension[0], walletProto); for (Protos.Tag tag : walletProto.getTagsList()) { wallet.setTag(tag.getTag(), tag.getData()); } for (Protos.TransactionSigner signerProto : walletProto.getTransactionSignersList()) { try { Class signerClass = Class.forName(signerProto.getClassName()); TransactionSigner signer = (TransactionSigner) signerClass.newInstance(); signer.deserialize(signerProto.getData().toByteArray()); wallet.addTransactionSigner(signer); } catch (Exception e) { throw new UnreadableWalletException( "Unable to deserialize TransactionSigner instance: " + signerProto.getClassName(), e); } } if (walletProto.hasVersion()) { wallet.setVersion(walletProto.getVersion()); } // Make sure the object can be re-used to read another wallet without corruption. txMap.clear(); return wallet; }