mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-15 11:45:51 +00:00
Remove BlockChainListener.isTransactionRelevant.
The optimisation this was meant to support ceased to be relevant a long time ago.
This commit is contained in:
parent
43b89f4678
commit
30d2da2947
@ -374,21 +374,13 @@ public abstract class AbstractBlockChain {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Does this block contain any transactions we might care about? Check this up front before verifying the
|
||||
// blocks validity so we can skip the merkle root verification if the contents aren't interesting. This saves
|
||||
// a lot of time for big blocks.
|
||||
boolean contentsImportant = shouldVerifyTransactions();
|
||||
if (block.transactions != null) {
|
||||
contentsImportant = contentsImportant || containsRelevantTransactions(block);
|
||||
}
|
||||
|
||||
// Prove the block is internally valid: hash is lower than target, etc. This only checks the block contents
|
||||
// if there is a tx sending or receiving coins using an address in one of our wallets. And those transactions
|
||||
// are only lightly verified: presence in a valid connecting block is taken as proof of validity. See the
|
||||
// article here for more details: http://code.google.com/p/bitcoinj/wiki/SecurityModel
|
||||
try {
|
||||
block.verifyHeader();
|
||||
if (contentsImportant)
|
||||
if (shouldVerifyTransactions())
|
||||
block.verifyTransactions();
|
||||
} catch (VerificationException e) {
|
||||
log.error("Failed to verify block: ", e);
|
||||
@ -765,12 +757,10 @@ public abstract class AbstractBlockChain {
|
||||
Set<Sha256Hash> falsePositives) throws VerificationException {
|
||||
for (Transaction tx : transactions) {
|
||||
try {
|
||||
if (listener.isTransactionRelevant(tx)) {
|
||||
falsePositives.remove(tx.getHash());
|
||||
if (clone)
|
||||
tx = new Transaction(tx.params, tx.bitcoinSerialize());
|
||||
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
|
||||
}
|
||||
falsePositives.remove(tx.getHash());
|
||||
if (clone)
|
||||
tx = new Transaction(tx.params, tx.bitcoinSerialize());
|
||||
listener.receiveFromBlock(tx, block, blockType, relativityOffset++);
|
||||
} catch (ScriptException e) {
|
||||
// We don't want scripts we don't understand to break the block chain so just note that this tx was
|
||||
// not scanned here and continue.
|
||||
@ -826,26 +816,6 @@ public abstract class AbstractBlockChain {
|
||||
} while (blocksConnectedThisRound > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any connected wallet considers any transaction in the block to be relevant.
|
||||
*/
|
||||
private boolean containsRelevantTransactions(Block block) {
|
||||
// Does not need to be locked.
|
||||
for (Transaction tx : block.transactions) {
|
||||
try {
|
||||
for (final ListenerRegistration<BlockChainListener> registration : listeners) {
|
||||
if (registration.executor != Threading.SAME_THREAD) continue;
|
||||
if (registration.listener.isTransactionRelevant(tx)) return true;
|
||||
}
|
||||
} catch (ScriptException e) {
|
||||
// We don't want scripts we don't understand to break the block chain so just note that this tx was
|
||||
// not scanned here and continue.
|
||||
log.warn("Failed to parse a script: " + e.toString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block at the head of the current best chain. This is the block which represents the greatest
|
||||
* amount of cumulative work done.
|
||||
|
@ -30,11 +30,6 @@ public class AbstractBlockChainListener implements BlockChainListener {
|
||||
public void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType,
|
||||
int relativityOffset) throws VerificationException {
|
||||
|
@ -45,15 +45,6 @@ public interface BlockChainListener {
|
||||
void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks,
|
||||
List<StoredBlock> newBlocks) throws VerificationException;
|
||||
|
||||
/**
|
||||
* Returns true if the given transaction is interesting to the listener. If yes, then the transaction will
|
||||
* be provided via the receiveFromBlock method. This method is essentially an optimization that lets BlockChain
|
||||
* bypass verification of a blocks merkle tree if no listeners are interested, which can save time when processing
|
||||
* full blocks on mobile phones. It's likely the method will be removed in future and replaced with an alternative
|
||||
* mechanism that involves listeners providing all keys that are interesting.
|
||||
*/
|
||||
boolean isTransactionRelevant(Transaction tx) throws ScriptException;
|
||||
|
||||
/**
|
||||
* <p>Called by the {@link BlockChain} when we receive a new block that contains a relevant transaction.</p>
|
||||
*
|
||||
|
@ -1694,7 +1694,6 @@ public class Wallet extends BaseTaggableObject implements BlockChainListener, Pe
|
||||
* <p>Note that if the tx has inputs containing one of our keys, but the connected transaction is not in the wallet,
|
||||
* it will not be considered relevant.</p>
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransactionRelevant(Transaction tx) throws ScriptException {
|
||||
lock.lock();
|
||||
try {
|
||||
@ -1761,6 +1760,8 @@ public class Wallet extends BaseTaggableObject implements BlockChainListener, Pe
|
||||
int relativityOffset) throws VerificationException {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!isTransactionRelevant(tx))
|
||||
return;
|
||||
receive(tx, block, blockType, relativityOffset);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
@ -1771,6 +1772,7 @@ public class Wallet extends BaseTaggableObject implements BlockChainListener, Pe
|
||||
int relativityOffset) throws VerificationException {
|
||||
// Runs in a peer thread.
|
||||
checkState(lock.isHeldByCurrentThread());
|
||||
|
||||
Coin prevBalance = getBalance();
|
||||
Sha256Hash txHash = tx.getHash();
|
||||
boolean bestChain = blockType == BlockChain.NewBlockType.BEST_CHAIN;
|
||||
|
@ -34,9 +34,6 @@ public class NativeBlockChainListener implements BlockChainListener {
|
||||
@Override
|
||||
public native void reorganize(StoredBlock splitPoint, List<StoredBlock> oldBlocks, List<StoredBlock> newBlocks) throws VerificationException;
|
||||
|
||||
@Override
|
||||
public native boolean isTransactionRelevant(Transaction tx) throws ScriptException;
|
||||
|
||||
@Override
|
||||
public native void receiveFromBlock(Transaction tx, StoredBlock block, BlockChain.NewBlockType blockType,
|
||||
int relativityOffset) throws VerificationException;
|
||||
|
@ -79,7 +79,7 @@ public class BlockChainTest {
|
||||
int relativityOffset) throws VerificationException {
|
||||
super.receiveFromBlock(tx, block, blockType, relativityOffset);
|
||||
BlockChainTest.this.block[0] = block;
|
||||
if (tx.isCoinBase()) {
|
||||
if (isTransactionRelevant(tx) && tx.isCoinBase()) {
|
||||
BlockChainTest.this.coinbaseTransaction = tx;
|
||||
}
|
||||
}
|
||||
@ -135,35 +135,6 @@ public class BlockChainTest {
|
||||
assertTrue(wallet.getBalance().signum() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void merkleRoots() throws Exception {
|
||||
// Test that merkle root verification takes place when a relevant transaction is present and doesn't when
|
||||
// there isn't any such tx present (as an optimization).
|
||||
Transaction tx1 = createFakeTx(unitTestParams,
|
||||
COIN,
|
||||
wallet.currentReceiveKey().toAddress(unitTestParams));
|
||||
Block b1 = createFakeBlock(blockStore, tx1).block;
|
||||
chain.add(b1);
|
||||
resetBlockStore();
|
||||
Sha256Hash hash = b1.getMerkleRoot();
|
||||
b1.setMerkleRoot(Sha256Hash.ZERO_HASH);
|
||||
try {
|
||||
chain.add(b1);
|
||||
fail();
|
||||
} catch (VerificationException e) {
|
||||
// Expected.
|
||||
b1.setMerkleRoot(hash);
|
||||
}
|
||||
// Now add a second block with no relevant transactions and then break it.
|
||||
Transaction tx2 = createFakeTx(unitTestParams, COIN,
|
||||
new ECKey().toAddress(unitTestParams));
|
||||
Block b2 = createFakeBlock(blockStore, tx2).block;
|
||||
b2.getMerkleRoot();
|
||||
b2.setMerkleRoot(Sha256Hash.ZERO_HASH);
|
||||
b2.solve();
|
||||
chain.add(b2); // Broken block is accepted because its contents don't matter to us.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unconnectedBlocks() throws Exception {
|
||||
Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo);
|
||||
|
@ -275,6 +275,7 @@ public class TransactionTest {
|
||||
assertEquals(iterator.hasNext(), false);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = ScriptException.class)
|
||||
public void testAddSignedInputThrowsExceptionWhenScriptIsNotToRawPubKeyAndIsNotToAddress() {
|
||||
ECKey key = new ECKey();
|
||||
|
Loading…
x
Reference in New Issue
Block a user