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))
예제 #4
0
        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)
예제 #6
0
    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)
예제 #7
0
 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)
예제 #8
0
    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)
예제 #14
0
        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()
예제 #17
0
 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)
예제 #18
0
 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))