/** * Get a fresh address by marking the current receive address as used. It will throw * {@link Bip44KeyLookAheadExceededException} if we requested too many addresses that * exceed the BIP44 look ahead threshold. */ public BitAddress getFreshReceiveAddress() throws Bip44KeyLookAheadExceededException { lock.lock(); try { if (!canCreateFreshReceiveAddress()) { throw new Bip44KeyLookAheadExceededException(); } keys.getKey(RECEIVE_FUNDS); return currentAddress(RECEIVE_FUNDS); } finally { lock.unlock(); walletSaveNow(); } }
public BitAddress getFreshReceiveAddress(boolean isManualAddressManagement) throws Bip44KeyLookAheadExceededException { lock.lock(); try { BitAddress newAddress = null; BitAddress freshAddress = getFreshReceiveAddress(); if (isManualAddressManagement) { newAddress = getLastUsedAddress(RECEIVE_FUNDS); } if (newAddress == null) { newAddress = freshAddress; } return newAddress; } finally { lock.unlock(); walletSaveNow(); } }
private void updateView() { adapter.replace(pocket.getIssuedReceiveAddresses(), pocket.getUsedAddresses()); }
public BitAddress getAddress(SimpleHDKeyChain.KeyPurpose purpose, boolean isManualAddressManagement) { BitAddress receiveAddress = null; if (isManualAddressManagement) { receiveAddress = getLastUsedAddress(purpose); } if (receiveAddress == null) { receiveAddress = currentAddress(purpose); } return receiveAddress; }
@Test public void serializeUnencryptedNormal() throws Exception { pocket.onConnection(getBlockchainConnection(DOGE)); Protos.WalletPocket walletPocketProto = pocket.toProtobuf(); System.out.println(walletPocketProto.toString()); assertEquals(pocket.getBalance().value, newPocket.getBalance().value); assertEquals(DOGE.value(11000000000l), newPocket.getBalance()); assertEquals(pocket.getCoinType(), newPocket.getCoinType()); assertEquals(pocket.getDescriptionOrCoinName(), newPocket.getDescriptionOrCoinName()); assertEquals(pocket.keys.toProtobuf().toString(), newPocket.keys.toProtobuf().toString()); assertEquals(pocket.getLastBlockSeenHash(), newPocket.getLastBlockSeenHash()); assertEquals(pocket.getLastBlockSeenHeight(), newPocket.getLastBlockSeenHeight()); assertEquals(pocket.getLastBlockSeenTimeSecs(), newPocket.getLastBlockSeenTimeSecs()); for (BitTransaction tx : pocket.getTransactions().values()) { assertEquals(tx, newPocket.getTransaction(tx.getHash())); BitTransaction txNew = checkNotNull(newPocket.getTransaction(tx.getHash())); assertInputsEquals(tx.getInputs(), txNew.getInputs()); assertOutputsEquals(tx.getOutputs(false), txNew.getOutputs(false)); for (AddressStatus status : pocket.getAllAddressStatus()) { if (status.getStatus() == null) continue; assertEquals(status, newPocket.getAddressStatus(status.getAddress())); newPocket.onConnection(getBlockchainConnection(DOGE)); List<AbstractAddress> addressesToWatch = newPocket.getAddressesToWatch();
public static Protos.WalletPocket toProtobuf(WalletPocketHD pocket) { walletBuilder.setNetworkIdentifier(pocket.getCoinType().getId()); if (pocket.getDescription() != null) { walletBuilder.setDescription(pocket.getDescription()); if (pocket.getId() != null) { walletBuilder.setId(pocket.getId()); for (AddressStatus status : pocket.getAllAddressStatus()) { Protos.AddressStatus.Builder addressStatus = Protos.AddressStatus.newBuilder(); if (status.getStatus() == null) { for (WalletTransaction wtx : pocket.getWalletTransactions()) { Protos.Transaction txProto = makeTxProto(wtx); walletBuilder.addTransaction(txProto); walletBuilder.addAllKey(pocket.serializeKeychainToProtobuf()); if (pocket.getLastBlockSeenHash() != null) { walletBuilder.setLastSeenBlockHash(hashToByteString(pocket.getLastBlockSeenHash())); if (pocket.getLastBlockSeenHeight() >= 0) { walletBuilder.setLastSeenBlockHeight(pocket.getLastBlockSeenHeight()); if (pocket.getLastBlockSeenTimeSecs() > 0) { walletBuilder.setLastSeenBlockTimeSecs(pocket.getLastBlockSeenTimeSecs());
@Test public void issuedKeysLimit2() throws Exception { assertTrue(pocket.canCreateFreshReceiveAddress()); try { for (int i = 0; i < 100; i++) { pocket.getFreshReceiveAddress(); } } catch (Bip44KeyLookAheadExceededException e) { assertFalse(pocket.canCreateFreshReceiveAddress()); // We haven't used any key so the total must be 20 - 1 (the unused key) assertEquals(19, pocket.getNumberIssuedReceiveAddresses()); assertEquals(19, pocket.getIssuedReceiveAddresses().size()); } }
pocket = new WalletPocketHD(walletProto.getId(), chain, coinType); } else { pocket = new WalletPocketHD(chain, coinType); pocket.setDescription(walletProto.getDescription()); pocket.restoreWalletTransactions(wtxs); proto.getOutPointIndex() & 0xFFFFFFFFL, proto.getScriptBytes().toByteArray()); pocket.addUnspentOutput( new OutPointOutput(utxo, proto.getIsGenerated())); AbstractAddress addr = coinType.newAddress(sp.getAddress()); AddressStatus status = new AddressStatus(addr, sp.getStatus()); pocket.commitAddressStatus(status); pocket.setLastBlockSeenHash(null); } else { pocket.setLastBlockSeenHash(byteStringToHash(walletProto.getLastSeenBlockHash())); pocket.setLastBlockSeenHeight(-1); } else { pocket.setLastBlockSeenHeight(walletProto.getLastSeenBlockHeight()); pocket.setLastBlockSeenTimeSecs(walletProto.getLastSeenBlockTimeSecs()); pocket.refresh(); } finally {
private void createAddress(WalletPocketHD account, @Nullable String newLabel) { if (account.canCreateFreshReceiveAddress()) { try { AbstractAddress newAddress = account.getFreshReceiveAddress( app.getConfiguration().isManualAddressManagement()); if (newLabel != null && !newLabel.isEmpty()) { final Uri uri = AddressBookProvider.contentUri(getActivity().getPackageName(), account.getCoinType()) .buildUpon().appendPath(newAddress.toString()).build(); final ContentValues values = new ContentValues(); values.put(AddressBookProvider.KEY_LABEL, newLabel); if (resolver != null) resolver.insert(uri, values); } } catch (Bip44KeyLookAheadExceededException e) { // Should not happen as we already checked if we can create a new address Toast.makeText(getActivity(), R.string.too_many_unused_addresses, Toast.LENGTH_LONG).show(); } } else { Toast.makeText(getContext(), R.string.too_many_unused_addresses, Toast.LENGTH_LONG).show(); } } }
private Sha256Hash send(Value value, WalletPocketHD w1, WalletPocketHD w2) throws Exception { assertEquals(w1.getCoinType(), w2.getCoinType()); CoinType type = w1.getCoinType(); BitSendRequest req = w1.sendCoinsOffline(w2.getReceiveAddress(), value); req.feePerTxSize = type.value("0.01"); w1.completeAndSignTx(req); byte[] txBytes = req.tx.bitcoinSerialize(); w1.addNewTransactionIfNeeded(new BitTransaction(type, txBytes)); w2.addNewTransactionIfNeeded(new BitTransaction(type, txBytes)); return req.tx.getHash(); }
@Test public void issuedKeys() throws Bip44KeyLookAheadExceededException { List<BitAddress> issuedAddresses = new ArrayList<>(); assertEquals(0, pocket.getIssuedReceiveAddresses().size()); assertEquals(0, pocket.keys.getNumIssuedExternalKeys()); issuedAddresses.add(0, pocket.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS)); BitAddress freshAddress = pocket.getFreshReceiveAddress(); assertEquals(freshAddress, pocket.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS)); assertEquals(1, pocket.getIssuedReceiveAddresses().size()); assertEquals(1, pocket.keys.getNumIssuedExternalKeys()); assertEquals(issuedAddresses, pocket.getIssuedReceiveAddresses()); issuedAddresses.add(0, pocket.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS)); freshAddress = pocket.getFreshReceiveAddress(); assertEquals(freshAddress, pocket.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS)); assertEquals(2, pocket.getIssuedReceiveAddresses().size()); assertEquals(2, pocket.keys.getNumIssuedExternalKeys()); assertEquals(issuedAddresses, pocket.getIssuedReceiveAddresses()); }
@Test public void serializeTransactionsVpn() throws Exception, Bip44KeyLookAheadExceededException { WalletPocketHD account = new WalletPocketHD(rootKey, VPN, null, null); tx.addOutput(VPN.oneCoin().toCoin(), account.getFreshReceiveAddress()); account.addNewTransactionIfNeeded(tx); WalletPocketHD newAccount = testWalletSerializationForCoin(account); Transaction newTx = newAccount.getRawTransaction(tx.getHash()); assertNotNull(newTx); assertNotNull(newTx.getExtraBytes()); tx.setTime(0x99999999); tx.setExtraBytes(new byte[0]); tx.addOutput(VPN.oneCoin().toCoin(), account.getFreshReceiveAddress()); account.addNewTransactionIfNeeded(tx); newAccount = testWalletSerializationForCoin(account); newTx = newAccount.getRawTransaction(tx.getHash()); assertNotNull(newTx); assertNotNull(newTx.getExtraBytes()); byte[] bytes = {0x1, 0x2, 0x3}; tx.setExtraBytes(bytes); tx.addOutput(VPN.oneCoin().toCoin(), account.getFreshReceiveAddress()); account.addNewTransactionIfNeeded(tx); newAccount = testWalletSerializationForCoin(account); newTx = newAccount.getRawTransaction(tx.getHash()); assertNotNull(newTx); assertArrayEquals(bytes, newTx.getExtraBytes());
@Test public void signMessageEncryptedFailed() throws AddressMalformedException, MissingPrivateKeyException, KeyIsEncryptedException { WalletPocketHD pocketHD = new WalletPocketHD(rootKey, BTC, null, null); pocketHD.getReceiveAddress(); // Generate the first key pocketHD.encrypt(crypter, aesKey); SignedMessage signedMessage = new SignedMessage("1KUDsEDqSBAgxubSEWszoA9xscNRRCmujM", MESSAGE); pocketHD.signMessage(signedMessage, null); assertEquals(SignedMessage.Status.KeyIsEncrypted, signedMessage.status); }
@Test public void serializeTransactionsNbt() throws Exception, Bip44KeyLookAheadExceededException { WalletPocketHD account = new WalletPocketHD(rootKey, NBT, null, null); Transaction tx = new Transaction(NBT); tx.addOutput(NBT.oneCoin().toCoin(), account.getReceiveAddress()); account.addNewTransactionIfNeeded(tx); testWalletSerializationForCoin(account); }
@Test public void testSendingAndBalances() throws Exception { DeterministicHierarchy h = new DeterministicHierarchy(masterKey); WalletPocketHD account1 = new WalletPocketHD(h.get(BTC.getBip44Path(0), false, true), BTC, null, null); WalletPocketHD account2 = new WalletPocketHD(h.get(BTC.getBip44Path(1), false, true), BTC, null, null); WalletPocketHD account3 = new WalletPocketHD(h.get(BTC.getBip44Path(2), false, true), BTC, null, null); tx.addOutput(BTC.oneCoin().toCoin(), account1.getReceiveAddress()); tx.getConfidence().setSource(Source.SELF); account1.addNewTransactionIfNeeded(tx); assertEquals(BTC.value("1"), account1.getBalance()); assertEquals(BTC.value("0"), account2.getBalance()); assertEquals(BTC.value("0"), account3.getBalance()); assertEquals(BTC.value("0.94"), account1.getBalance()); assertEquals(BTC.value("0"), account2.getBalance()); assertEquals(BTC.value("0"), account3.getBalance()); assertEquals(BTC.value("0.94"), account1.getBalance()); assertEquals(BTC.value("0.05"), account2.getBalance()); assertEquals(BTC.value("0.86"), account1.getBalance()); assertEquals(BTC.value("0.05"), account2.getBalance()); assertEquals(BTC.value("0.07"), account3.getBalance()); assertEquals(BTC.value("0.86"), account1.getBalance()); assertEquals(BTC.value("0.01"), account2.getBalance()); assertEquals(BTC.value("0.1"), account3.getBalance());
@Test public void xpubWalletSerialized() throws Exception { WalletPocketHD account = new WalletPocketHD(rootKey, BTC, null, null); Protos.WalletPocket proto = account.toProtobuf(); WalletPocketHD newAccount = new WalletPocketProtobufSerializer().readWallet(proto, null); assertEquals(account.getPublicKeySerialized(), newAccount.getPublicKeySerialized()); }
@Test public void signMessage() throws AddressMalformedException, MissingPrivateKeyException, KeyIsEncryptedException { WalletPocketHD pocketHD = new WalletPocketHD(rootKey, BTC, null, null); pocketHD.getReceiveAddress(); // Generate the first key SignedMessage signedMessage = new SignedMessage("1KUDsEDqSBAgxubSEWszoA9xscNRRCmujM", MESSAGE); pocketHD.signMessage(signedMessage, null); assertEquals(EXPECTED_BITCOIN_SIG, signedMessage.getSignature()); signedMessage = new SignedMessage("1KUDsEDqSBAgxubSEWszoA9xscNRRCmujM", MESSAGE_UNICODE); pocketHD.signMessage(signedMessage, null); assertEquals(EXPECTED_BITCOIN_SIG_UNICODE, signedMessage.getSignature()); pocketHD = new WalletPocketHD(rootKey, NBT, null, null); pocketHD.getReceiveAddress(); // Generate the first key signedMessage = new SignedMessage("BNvJUwg3BgkbQk5br1CxvHxdcDp1EC3saE", MESSAGE); pocketHD.signMessage(signedMessage, null); assertEquals(EXPECTED_NUBITS_SIG, signedMessage.getSignature()); signedMessage = new SignedMessage("BNvJUwg3BgkbQk5br1CxvHxdcDp1EC3saE", MESSAGE_UNICODE); pocketHD.signMessage(signedMessage, null); assertEquals(EXPECTED_NUBITS_SIG_UNICODE, signedMessage.getSignature()); }
@Override public BitAddress getChangeAddress() { return currentAddress(CHANGE); }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { accountId = getArguments().getString(Constants.ARG_ACCOUNT_ID); } WalletApplication walletApplication = (WalletApplication) getActivity().getApplication(); // TODO pocket = (WalletPocketHD) walletApplication.getAccount(accountId); if (pocket == null) { Toast.makeText(getActivity(), R.string.no_such_pocket_error, Toast.LENGTH_LONG).show(); return; } type = pocket.getCoinType(); }
@Test public void xpubWallet() { String xpub = "xpub67tVq9TLPPoaHVSiYu8mqahm3eztTPUts6JUftNq3pZF1PJwjknrTqQhjc2qRGd6vS8wANu7mLnqkiUzFZ1xZsAZoUMi8o6icMhzGCAhcSW"; DeterministicKey key = DeterministicKey.deserializeB58(null, xpub); WalletPocketHD account = new WalletPocketHD(key, BTC, null, null); assertEquals("1KUDsEDqSBAgxubSEWszoA9xscNRRCmujM", account.getReceiveAddress().toString()); account = new WalletPocketHD(key, NBT, null, null); assertEquals("BNvJUwg3BgkbQk5br1CxvHxdcDp1EC3saE", account.getReceiveAddress().toString()); }