Browse Source

verifier: request proofs in batches

3.3.3.1
SomberNight 7 years ago
parent
commit
2187615c08
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 1
      electrum/network.py
  2. 25
      electrum/verifier.py

1
electrum/network.py

@ -719,7 +719,6 @@ class Network(PrintError):
pass pass
async def get_merkle_for_transaction(self, tx_hash, tx_height): async def get_merkle_for_transaction(self, tx_hash, tx_height):
print("getting merkle for transaction", tx_hash, tx_height)
return await self.interface.session.send_request('blockchain.transaction.get_merkle', [tx_hash, tx_height]) return await self.interface.session.send_request('blockchain.transaction.get_merkle', [tx_hash, tx_height])
def broadcast_transaction(self, tx): def broadcast_transaction(self, tx):

25
electrum/verifier.py

@ -24,6 +24,8 @@
import asyncio import asyncio
from typing import Sequence, Optional from typing import Sequence, Optional
from aiorpcx import TaskGroup
from .util import ThreadJob, bh2u, VerifiedTxInfo, aiosafe from .util import ThreadJob, bh2u, VerifiedTxInfo, aiosafe
from .bitcoin import Hash, hash_decode, hash_encode from .bitcoin import Hash, hash_decode, hash_encode
from .transaction import Transaction from .transaction import Transaction
@ -49,10 +51,10 @@ class SPV(ThreadJob):
@aiosafe @aiosafe
async def main(self): async def main(self):
while True: while True:
await self.run() await self._request_proofs()
await asyncio.sleep(1) await asyncio.sleep(1)
async def run(self): async def _request_proofs(self):
blockchain = self.network.blockchain() blockchain = self.network.blockchain()
if not blockchain: if not blockchain:
self.print_error("no blockchain") self.print_error("no blockchain")
@ -60,7 +62,8 @@ class SPV(ThreadJob):
local_height = self.network.get_local_height() local_height = self.network.get_local_height()
unverified = self.wallet.get_unverified_txs() unverified = self.wallet.get_unverified_txs()
#print("verifier run", len(unverified))
async with TaskGroup() as group:
for tx_hash, tx_height in unverified.items(): for tx_hash, tx_height in unverified.items():
# do not request merkle branch before headers are available # do not request merkle branch before headers are available
if tx_height <= 0 or tx_height > local_height: if tx_height <= 0 or tx_height > local_height:
@ -70,23 +73,19 @@ class SPV(ThreadJob):
if header is None: if header is None:
index = tx_height // 2016 index = tx_height // 2016
if index < len(blockchain.checkpoints): if index < len(blockchain.checkpoints):
await self.network.request_chunk(tx_height, None) await group.spawn(self.network.request_chunk, tx_height, None)
elif (tx_hash not in self.requested_merkle elif (tx_hash not in self.requested_merkle
and tx_hash not in self.merkle_roots): and tx_hash not in self.merkle_roots):
self.print_error('requested merkle', tx_hash) self.print_error('requested merkle', tx_hash)
self.requested_merkle.add(tx_hash) self.requested_merkle.add(tx_hash)
self.verify_merkle(tx_hash, await self.network.get_merkle_for_transaction( await group.spawn(self._request_and_verify_single_proof, tx_hash, tx_height)
tx_hash,
tx_height
))
if self.network.blockchain() != self.blockchain: if self.network.blockchain() != self.blockchain:
self.blockchain = self.network.blockchain() self.blockchain = self.network.blockchain()
self.undo_verifications() self._undo_verifications()
def verify_merkle(self, tx_hash, merkle): async def _request_and_verify_single_proof(self, tx_hash, tx_height):
if self.wallet.verifier is None: merkle = await self.network.get_merkle_for_transaction(tx_hash, tx_height)
return # we have been killed, this was just an orphan callback
# Verify the hash of the server-provided merkle branch to a # Verify the hash of the server-provided merkle branch to a
# transaction matches the merkle root of its block # transaction matches the merkle root of its block
tx_height = merkle.get('block_height') tx_height = merkle.get('block_height')
@ -143,7 +142,7 @@ class SPV(ThreadJob):
else: else:
raise InnerNodeOfSpvProofIsValidTx() raise InnerNodeOfSpvProofIsValidTx()
def undo_verifications(self): def _undo_verifications(self):
height = self.blockchain.get_forkpoint() height = self.blockchain.get_forkpoint()
tx_hashes = self.wallet.undo_verifications(self.blockchain, height) tx_hashes = self.wallet.undo_verifications(self.blockchain, height)
for tx_hash in tx_hashes: for tx_hash in tx_hashes:

Loading…
Cancel
Save