3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 15:22:16 +00:00

Bloom bugfix: track false positives in blocks including when the tx was broadcast within the session, and don't print an error from the wallet in this case. Should have no impact beyond more accurate FP rate calculations.

This commit is contained in:
Mike Hearn 2014-05-28 18:44:43 +02:00
parent 344be21821
commit e95fef3504
5 changed files with 32 additions and 21 deletions

View File

@ -498,8 +498,8 @@ public abstract class AbstractBlockChain {
// (in the case of the listener being a wallet). Wallets need to know how deep each transaction is so
// coinbases aren't used before maturity.
boolean first = true;
Set<Transaction> falsePositives = Sets.newHashSet();
if (filteredTxn != null) falsePositives.addAll(filteredTxn.values());
Set<Sha256Hash> falsePositives = Sets.newHashSet();
if (filteredTxHashList != null) falsePositives.addAll(filteredTxHashList);
for (final ListenerRegistration<BlockChainListener> registration : listeners) {
if (registration.executor == Threading.SAME_THREAD) {
informListenerForNewTransactions(block, newBlockType, filteredTxHashList, filteredTxn,
@ -514,7 +514,7 @@ public abstract class AbstractBlockChain {
public void run() {
try {
// We can't do false-positive handling when executing on another thread
Set<Transaction> ignoredFalsePositives = Sets.newHashSet();
Set<Sha256Hash> ignoredFalsePositives = Sets.newHashSet();
informListenerForNewTransactions(block, newBlockType, filteredTxHashList, filteredTxn,
newStoredBlock, notFirst, registration.listener, ignoredFalsePositives);
if (newBlockType == NewBlockType.BEST_CHAIN)
@ -539,7 +539,7 @@ public abstract class AbstractBlockChain {
@Nullable Map<Sha256Hash, Transaction> filteredTxn,
StoredBlock newStoredBlock, boolean first,
BlockChainListener listener,
Set<Transaction> falsePositives) throws VerificationException {
Set<Sha256Hash> falsePositives) throws VerificationException {
if (block.transactions != null) {
// If this is not the first wallet, ask for the transactions to be duplicated before being given
// to the wallet when relevant. This ensures that if we have two connected wallets and a tx that
@ -556,11 +556,14 @@ public abstract class AbstractBlockChain {
int relativityOffset = 0;
for (Sha256Hash hash : filteredTxHashList) {
Transaction tx = filteredTxn.get(hash);
if (tx != null)
if (tx != null) {
sendTransactionsToListener(newStoredBlock, newBlockType, listener, relativityOffset,
Arrays.asList(tx), !first, falsePositives);
else
listener.notifyTransactionIsInBlock(hash, newStoredBlock, newBlockType, relativityOffset);
} else {
if (listener.notifyTransactionIsInBlock(hash, newStoredBlock, newBlockType, relativityOffset)) {
falsePositives.remove(hash);
}
}
relativityOffset++;
}
}
@ -726,11 +729,11 @@ public abstract class AbstractBlockChain {
int relativityOffset,
List<Transaction> transactions,
boolean clone,
Set<Transaction> falsePositives) throws VerificationException {
Set<Sha256Hash> falsePositives) throws VerificationException {
for (Transaction tx : transactions) {
try {
if (listener.isTransactionRelevant(tx)) {
falsePositives.remove(tx);
falsePositives.remove(tx.getHash());
if (clone)
tx = new Transaction(tx.params, tx.bitcoinSerialize());
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);

View File

@ -41,7 +41,8 @@ public class AbstractBlockChainListener implements BlockChainListener {
}
@Override
public void notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, BlockChain.NewBlockType blockType,
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, BlockChain.NewBlockType blockType,
int relativityOffset) throws VerificationException {
return false;
}
}

View File

@ -81,8 +81,14 @@ public interface BlockChainListener {
* <p>The relativityOffset parameter in this case is an arbitrary (meaningless) number, that is useful only when
* compared to the relativity count of another transaction received inside the same block. It is used to establish
* an ordering of transactions relative to one another.</p>
*
* <p>This method should return false if the given tx hash isn't known about, e.g. because the the transaction was
* a Bloom false positive. If it was known about and stored, it should return true. The caller may need to know
* this to calculate the effective FP rate.</p>
*
* @return whether the transaction is known about i.e. was considered relevant previously.
*/
void notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
BlockChain.NewBlockType blockType,
int relativityOffset) throws VerificationException;
}

View File

@ -617,7 +617,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* inactive side chain. We must still record these transactions and the blocks they appear in because a future
* block might change which chain is best causing a reorganize. A re-org can totally change our balance!
*/
public void notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
public boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block,
BlockChain.NewBlockType blockType,
int relativityOffset) throws VerificationException {
lock.lock();
@ -629,8 +629,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// If this happens our risk analysis is probably wrong and should be improved.
log.info("Risk analysis dropped tx {} but was included in block anyway", tx.getHash());
} else {
log.error("TX {} not found despite being sent to wallet", txHash);
return;
// False positive that was broadcast to us and ignored by us because it was irrelevant to our keys.
return false;
}
}
receive(tx, block, blockType, relativityOffset);
@ -642,6 +642,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
// This has to run outside the wallet lock as it may trigger broadcasting of new transactions.
maybeRotateKeys();
}
return true;
}
/**

View File

@ -42,6 +42,6 @@ public class NativeBlockChainListener implements BlockChainListener {
int relativityOffset) throws VerificationException;
@Override
public native void notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, BlockChain.NewBlockType blockType,
public native boolean notifyTransactionIsInBlock(Sha256Hash txHash, StoredBlock block, BlockChain.NewBlockType blockType,
int relativityOffset) throws VerificationException;
}