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:
parent
e263229b62
commit
394d0b788d
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user