async def async_tests(): cli = ElectrumConnection() await cli.connect() spends = n.listunspent() await self.test_basic(n, spends, cli) await self.test_duplicate_registration(n, spends, cli)
async def test_unsubscribe(self, n, subscribe, unsubscribe, addr_converter): cli = ElectrumConnection() await cli.connect() addr = n.getnewaddress() _, queue = await cli.subscribe(subscribe, addr_converter(addr)) # Verify that we're receiving notifications n.sendtoaddress(addr, 10) subscription_name, _ = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(addr_converter(addr), subscription_name) ok = await cli.call(unsubscribe, addr_converter(addr)) assert (ok) # Verify that we're no longer receiving notifications n.sendtoaddress(addr, 10) try: await asyncio.wait_for(queue.get(), timeout=10) assert (False) # Should have timed out. except asyncio.TimeoutError: pass # Unsubscribing from a hash we're not subscribed to should return false ok = await cli.call(unsubscribe, addr_converter(n.getnewaddress())) assert (not ok)
async def test_subscribe_headers(self, n): cli = ElectrumConnection() await cli.connect() headers = [] logging.info( "Calling subscribe should return the current best block header") result, queue = await cli.subscribe('blockchain.headers.subscribe') assert_equal(n.getblockheader(n.getbestblockhash(), False), result['hex']) logging.info( "Now generate 10 blocks, check that these are pushed to us.") async def test(): for _ in range(10): blockhashes = n.generate(1) header_hex = n.getblockheader(blockhashes.pop(), False) notified = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(header_hex, notified.pop()['hex']) start = time.time() await test() logging.info("Getting 10 block notifications took {} seconds".format( time.time() - start))
async def async_tests(loop): cli = ElectrumConnection(loop) await cli.connect() return await asyncio.gather( self.test_verbose(n, cli, nonstandard_tx.hash, p2sh_tx.hash, p2pkh_tx.hash, unconfirmed_tx.hash), self.test_non_verbose(cli, coinbases, unconfirmed_tx))
async def async_tests(): await self.test_multiple_client_subs(n) cli = ElectrumConnection() await cli.connect() await self.test_unsubscribe_scripthash(n, cli) await self.test_subscribe_headers(n, cli) await self.test_subscribe_scripthash(n, cli)
def run_test(self): n = self.nodes[0] n.generate(1) sync_electrum_height(n) cli = ElectrumConnection() self.test_subscribe_headers(n, cli) self.test_subscribe_scripthash(n, cli)
async def async_tests(): await self.test_get_frist_use(n) cli = ElectrumConnection() await cli.connect() await self.test_invalid_args(cli) await self.test_get_balance(n, cli) await self.test_get_history(n, cli) await self.test_list_unspent(n, cli)
async def test_get_frist_use(self, n): cli = ElectrumConnection() await cli.connect() # New address that has never received coins. Should return an error. addr = n.getnewaddress() await assert_raises_async(ElectrumErrorResponse, cli.call, "blockchain.address.get_first_use", addr) await assert_raises_async(ElectrumErrorResponse, cli.call, "blockchain.scripthash.get_first_use", address_to_scripthash(addr)) # Send coin to the new address txid = await self.sendtoaddr(n, cli, addr, 1) # Wait for electrum server to see the utxo. async def wait_for_utxo(): utxo = await cli.call("blockchain.address.listunspent", addr) if len(utxo) == 1: return utxo return None utxo = await waitForAsync(10, wait_for_utxo) # Observe that get_first_use returns the tx when it's in the mempool res = await cli.call("blockchain.address.get_first_use", addr) res2 = await cli.call("blockchain.scripthash.get_first_use", address_to_scripthash(addr)) assert_equal(res, res2) assert_equal( "0000000000000000000000000000000000000000000000000000000000000000", res['block_hash']) assert_equal(0, res['height']) assert_equal(txid, res['tx_hash']) # Confirm tx, observe that block height and gets set. n.generate(1) sync_electrum_height(n) res = await cli.call("blockchain.address.get_first_use", addr) res2 = await cli.call("blockchain.scripthash.get_first_use", address_to_scripthash(addr)) assert_equal(res, res2) assert_equal(n.getbestblockhash(), res['block_hash']) assert_equal(n.getblockcount(), res['height']) assert_equal(txid, res['tx_hash']) # Send another tx, observe that the first one is till returned. txid2 = await self.sendtoaddr(n, cli, addr, 2) res = await cli.call("blockchain.address.get_first_use", addr) assert_equal(txid, res['tx_hash']) # Also when the second tx is confirmed, the first is returned. n.generate(1) sync_electrum_height(n) res = await cli.call("blockchain.address.get_first_use", addr) assert_equal(txid, res['tx_hash'])
async def async_tests(): electrum_client = ElectrumConnection() await electrum_client.connect() res = await electrum_client.call("server.features") # Keys that the server MUST support assert_equal(n.getblockhash(0), res['genesis_hash']) assert_equal("sha256", res['hash_function']) assert (versiontuple(res['protocol_min']) >= versiontuple("1.4")) assert (versiontuple(res['protocol_max']) >= versiontuple("1.4")) assert (len(res['server_version']))
async def test_subscribe_limit(self, n): cli = ElectrumConnection() await cli.connect() logging.info("Testing scripthash subscription limit.") # Subscribe up to limit scripthashes = [] for i in range(0, MAX_SCRIPTHASH_SUBSCRIPTIONS): s = address_to_scripthash(n.getnewaddress()) await cli.subscribe('blockchain.scripthash.subscribe', s) scripthashes.append(s) # Next subscription should fail s = address_to_scripthash(n.getnewaddress()) await assert_raises_async(ElectrumErrorResponse, cli.call, "blockchain.scripthash.subscribe", s) try: await cli.call("blockchain.scripthash.subscribe", s) except ElectrumErrorResponse as e: error_code = "-32600" assert error_code in str(e) assert "subscriptions limit reached" in str(e) # Subscribing to an existing subscription should not affect the limit. await cli.subscribe('blockchain.scripthash.subscribe', scripthashes[0]) # Unsubscribing should allow for a new subscription ok = await cli.call('blockchain.scripthash.unsubscribe', scripthashes[0]) assert (ok) await cli.subscribe('blockchain.scripthash.subscribe', s) # ... and also enforce the limit again await assert_raises_async(ElectrumErrorResponse, cli.call, 'blockchain.scripthash.subscribe', address_to_scripthash(n.getnewaddress())) cli.disconnect()
async def test_scripthash_alias_limit(self, n): cli = ElectrumConnection() await cli.connect() addresses = [ "bitcoincash:ppwk8u8cg8cthr3jg0czzays6hsnysykes9amw07kv", "bitcoincash:qrsrvtc95gg8rrag7dge3jlnfs4j9pe0ugrmeml950" ] # Alias limit allows to subscribe to two addresses. for a in addresses: await cli.subscribe('blockchain.address.subscribe', a) # Third address should fail third = n.getnewaddress() await assert_raises_async(ElectrumErrorResponse, cli.call, "blockchain.address.subscribe", third) try: await cli.call("blockchain.address.subscribe", third) except ElectrumErrorResponse as e: error_code = "-32600" assert error_code in str(e) assert "alias subscriptions limit reached" in str(e) # Unsubscribing should allow for a new subscription ok = await cli.call('blockchain.address.unsubscribe', addresses[0]) assert (ok) await cli.subscribe('blockchain.address.subscribe', third) # ... and also enforce the limit again await assert_raises_async(ElectrumErrorResponse, cli.call, 'blockchain.address.subscribe', n.getnewaddress()) cli.disconnect()
async def test_multiple_client_subs(self, n): num_clients = 50 clients = [ElectrumConnection() for _ in range(0, num_clients)] [await c.connect() for c in clients] queues = [] addresses = [n.getnewaddress() for _ in range(0, num_clients)] # Send coins so the addresses, so they get a statushash [n.sendtoaddress(addresses[i], 1) for i in range(0, num_clients)] wait_for_electrum_mempool(n, count=num_clients) statushashes = [] queues = [] for i in range(0, num_clients): cli = clients[i] addr = addresses[i] scripthash = address_to_scripthash(addr) statushash, queue = await cli.subscribe( 'blockchain.scripthash.subscribe', scripthash) # should be unique assert (statushash is not None) assert (statushash not in statushashes) statushashes.append(statushash) queues.append(queue) # Send new coin to all, observe that all clients get a notification [n.sendtoaddress(addresses[i], 1) for i in range(0, num_clients)] for i in range(0, num_clients): q = queues[i] old_statushash = statushashes[i] scripthash, new_statushash = await asyncio.wait_for(q.get(), timeout=10) assert_equal(scripthash, address_to_scripthash(addresses[i])) assert (new_statushash != None) assert (new_statushash != old_statushash)
async def test_subscribe(self, n, subscribe, unsubscribe, addr_converter): cli = ElectrumConnection() await cli.connect() logging.info("Testing scripthash subscription") addr = n.getnewaddress() statushash, queue = await cli.subscribe(subscribe, addr_converter(addr)) logging.info("Unused address should not have a statushash") assert_equal(None, statushash) logging.info("Check notification on receiving coins") n.sendtoaddress(addr, 10) subscription_name, new_statushash1 = await asyncio.wait_for( queue.get(), timeout=10) assert_equal(addr_converter(addr), subscription_name) assert (new_statushash1 != None and len(new_statushash1) == 64) logging.info("Check notification on block confirmation") assert (len(n.getrawmempool()) == 1) n.generate(1) assert (len(n.getrawmempool()) == 0) subscription_name, new_statushash2 = await asyncio.wait_for( queue.get(), timeout=10) assert_equal(addr_converter(addr), subscription_name) assert (new_statushash2 != new_statushash1) assert (new_statushash2 != None) logging.info( "Check that we get notification when spending funds from address") n.sendtoaddress(n.getnewaddress(), n.getbalance(), "", "", True) subscription_name, new_statushash3 = await asyncio.wait_for( queue.get(), timeout=10) assert_equal(addr_converter(addr), subscription_name) assert (new_statushash3 != new_statushash2) assert (new_statushash3 != None) # Clear mempool n.generate(1)
async def async_tests(loop): cli = ElectrumConnection(loop) await cli.connect() await self.test_basic(n, cli)
async def async_tests(loop): cli = ElectrumConnection(loop) await cli.connect() await self.test_blockheight_confirmed(n, cli, coinbases.pop(0))
async def test_connection_limit(self, loop): connections = [] for i in range(MAX_RPC_CONNECTIONS): c = ElectrumConnection() await c.connect() connections.append(c) # Exceed limit, we should get disconnected. extra_connection = ElectrumConnection() await extra_connection.connect() try: await asyncio.wait_for(extra_connection.call("server.ping"), timeout=5) assert (False) except asyncio.TimeoutError: # We expect this to timeout pass waitFor(5, lambda: not extra_connection.is_connected()) # Drop one connection connections[0].disconnect() # New connection should be accepted now. extra_connection2 = ElectrumConnection() await extra_connection2.connect() await asyncio.wait_for(extra_connection2.call("server.ping"), timeout=5) for c in connections[1:] + [extra_connection2]: c.disconnect()
async def async_tests(): electrum_client = ElectrumConnection() await electrum_client.connect() await self.test_unknown_method(electrum_client) await self.test_invalid_args(electrum_client) await self.test_address_balance(n, electrum_client)
async def async_tests(loop): cli = ElectrumConnection(loop) await cli.connect() await self.test_blockheight_unconfirmed(n, cli, coinbases.pop(0)) await self.test_chain_to_from_one_scripthash( n, cli, coinbases.pop(0))