async def test_unsubscribe_scripthash(self, n, cli): addr = n.getnewaddress() scripthash = address_to_scripthash(addr) _, queue = await cli.subscribe('blockchain.scripthash.subscribe', scripthash) # Verify that we're receiving notifications n.sendtoaddress(addr, 10) sh, _ = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(scripthash, sh) ok = await cli.call('blockchain.scripthash.unsubscribe', scripthash) 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('blockchain.scripthash.unsubscribe', address_to_scripthash(n.getnewaddress())) assert (not ok)
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'])
def check_address(address, unconfirmed = 0, confirmed = 0): res = electrum_client.call("blockchain.scripthash.get_balance", address_to_scripthash(addr)) res = res["result"] return res["unconfirmed"] == unconfirmed * COIN \ and res["confirmed"] == confirmed * COIN
async def test_subscribe_scripthash(self, n, cli): logging.info("Testing scripthash subscription") addr = n.getnewaddress() scripthash = address_to_scripthash(addr) statushash, queue = await cli.subscribe( 'blockchain.scripthash.subscribe', scripthash) logging.info("Unused address should not have a statushash") assert_equal(None, statushash) logging.info("Check notification on receiving coins") n.sendtoaddress(addr, 10) sh, new_statushash1 = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(scripthash, sh) 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) sh, new_statushash2 = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(scripthash, sh) 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) sh, new_statushash3 = await asyncio.wait_for(queue.get(), timeout=10) assert_equal(scripthash, sh) assert (new_statushash3 != new_statushash2) assert (new_statushash3 != None)
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_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()
def test_address_balance(self, n, electrum_client): addr = n.getnewaddress() txhash = n.sendtoaddress(addr, 1) scripthash = address_to_scripthash(addr) def check_address(address, unconfirmed=0, confirmed=0): res = electrum_client.call("blockchain.scripthash.get_balance", address_to_scripthash(addr)) return res["unconfirmed"] == unconfirmed * COIN \ and res["confirmed"] == confirmed * COIN waitFor(10, lambda: check_address(scripthash, unconfirmed=1)) n.generate(1) waitFor(10, lambda: check_address(scripthash, confirmed=1))