3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Add Wallet.getBloomFilter and a test-case for it.

This commit is contained in:
Matt Corallo 2012-07-21 15:47:35 +02:00
parent e263229b62
commit 394d0b788d
2 changed files with 95 additions and 0 deletions

View File

@ -239,6 +239,13 @@ public class Wallet implements Serializable, BlockChainListener {
return new ArrayList<ECKey>(keychain);
}
/**
* Returns the number of keys in the keychain.
*/
public synchronized int getKeychainSize() {
return keychain.size();
}
private synchronized void saveToFile(File temp, File destFile) throws IOException {
// This odd construction exists to allow Android apps to control file permissions on the newly saved files
// created by the auto save thread. Android does not respect the standard Java file permission APIs in all
@ -2204,4 +2211,64 @@ public class Wallet implements Serializable, BlockChainListener {
public void setLastBlockSeenHash(Sha256Hash lastBlockSeenHash) {
this.lastBlockSeenHash = lastBlockSeenHash;
}
/**
* Gets the number of elements that will be added to a bloom filter returned by getBloomFilter
*/
public int getBloomFilterElementCount() {
int size = getKeychainSize() * 2;
for (Transaction tx : getTransactions(false, true)) {
for (TransactionOutput out : tx.getOutputs()) {
try {
if (out.isMine(this) && out.getScriptPubKey().isSentToRawPubKey())
size++;
} catch (ScriptException e) {
throw new RuntimeException(e); // If it is ours, we parsed the script corectly, so this shouldn't happen
}
}
}
return size;
}
/**
* Gets a bloom filter that contains all of the public keys from this wallet,
* and which will provide the given false-positive rate.
*
* See the docs for {@link BloomFilter#BloomFilter(int, double)} for a brief explanation of anonymity when using bloom filters.
*/
public BloomFilter getBloomFilter(double falsePositiveRate) {
return getBloomFilter(getBloomFilterElementCount(), falsePositiveRate, new Random().nextLong());
}
/**
* Gets a bloom filter that contains all of the public keys from this wallet,
* and which will provide the given false-positive rate if it has size elements.
* Keep in mind that you will get 2 elements in the bloom filter for each key in the wallet.
*
* This is used to generate a BloomFilter which can be #{link BloomFilter.merge}d with another.
* It could also be used if you have a specific target for the filter's size.
*
* See the docs for {@link BloomFilter#BloomFilter(int, double)} for a brief explanation of anonymity when using bloom filters.
*/
public synchronized BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) {
BloomFilter filter = new BloomFilter(size, falsePositiveRate, nTweak);
for (ECKey key : keychain) {
filter.insert(key.getPubKey());
filter.insert(key.getPubKeyHash());
}
for (Transaction tx : getTransactions(false, true)) {
for (int i = 0; i < tx.getOutputs().size(); i++) {
TransactionOutput out = tx.getOutputs().get(i);
try {
if (out.isMine(this) && out.getScriptPubKey().isSentToRawPubKey()) {
TransactionOutPoint outPoint = new TransactionOutPoint(params, i, tx);
filter.insert(outPoint.bitcoinSerialize());
}
} catch (ScriptException e) {
throw new RuntimeException(e); // If it is ours, we parsed the script corectly, so this shouldn't happen
}
}
}
return filter;
}
}

View File

@ -44,4 +44,32 @@ public class BloomFilterTest {
// Value generated by the reference client
assertTrue(Arrays.equals(Hex.decode("03ce42990500000001000080"), filter.bitcoinSerialize()));
}
@Test
public void walletTest() throws Exception {
NetworkParameters params = NetworkParameters.prodNet();
DumpedPrivateKey privKey = new DumpedPrivateKey(params, "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
Address addr = privKey.getKey().toAddress(params);
assertTrue(addr.toString().equals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e"));
Wallet wallet = new Wallet(params);
// Check that the wallet was created with no keys
// If wallets ever get created with keys, this test needs redone.
for (ECKey key : wallet.getKeys())
fail();
wallet.addKey(privKey.getKey());
// Add a random key which happens to have been used in a recent generation
wallet.addKey(new ECKey(null, Hex.decode("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99")));
wallet.commitTx(new Transaction(params, Hex.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038754030114062f503253482fffffffff01c05e559500000000232103cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99ac00000000")));
// We should have 2 per pubkey, and one for the pay-2-pubkey output we have
assertTrue(wallet.getBloomFilterElementCount() == 5);
BloomFilter filter = wallet.getBloomFilter(wallet.getBloomFilterElementCount(), 0.001, 0);
// Value generated by the reference client
assertTrue(Arrays.equals(Hex.decode("082ae5edc8e51d4a030800000000000000"), filter.bitcoinSerialize()));
}
}