import asyncio
from test_framework.utilcompat import lock, unlock
from test_framework.serialize import to_hex
from test_framework.script import OP_DEPTH, CScript, OP_DROP, OP_NOP, OP_TRUE
from test_framework.util import assert_equal
from test_framework.electrumutil import (
ElectrumTestFramework,
get_txid_from_idem,
)
from test_framework.environment import on_bch, on_nex
from test_framework.electrumconnection import ElectrumConnection
from test_framework.utiltx import pad_tx
if on_bch():
from test_framework.bch.blocktools import create_transaction
elif on_nex():
from test_framework.nex.blocktools import create_transaction
else:
raise NotImplementedError()
GET_UTXO = "blockchain.utxo.get"
TX_BROADCAST = "blockchain.transaction.broadcast"
class ElectrumUtxoTests(ElectrumTestFramework):
async def run_test(self):
await self.bootstrap_p2p()
cli = ElectrumConnection()
await cli.connect()
coinbases = await self.mine_blocks(cli, self.nodes[0], 106)
try:
await self.test_get_all(
cli, self.nodes[0], [coinbases.pop(0), coinbases.pop(0)]
)
if not on_nex():
await self.test_scriptsig_filter(
cli, self.nodes[0], [coinbases.pop(0), coinbases.pop(0)]
)
await self.test_scriptpubkey_filter(
cli, self.nodes[0], [coinbases.pop(0), coinbases.pop(0)]
)
finally:
cli.disconnect()
async def test_get_all(self, cli, n, utxos):
scriptpubkey = CScript([OP_NOP])
tx1 = create_transaction(
utxos[0],
n=0,
sig=unlock(CScript([])),
out=lock(scriptpubkey),
value=utxos[0].vout[0].n_value - 1000,
)
pad_tx(tx1)
tx2 = create_transaction(
utxos[1],
n=0,
sig=unlock(CScript([])),
out=lock(scriptpubkey),
value=utxos[1].vout[0].n_value - 1000,
)
pad_tx(tx2)
n = self.nodes[0]
mempool = await cli.call("mempool.get")
assert_equal(0, len(mempool["transactions"]))
tx1_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx1.to_hex()))
tx2_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx2.to_hex()))
await self.wait_for_mempool_count(cli, count=2)
mempool = await cli.call("mempool.get")
print(mempool)
assert_equal(2, len(mempool["transactions"]))
assert tx1_id in mempool["transactions"]
assert tx2_id in mempool["transactions"]
await self.mine_blocks(cli, n, 1, [tx1, tx2])
async def test_scriptsig_filter(self, cli, n, coinbases):
scriptpubkey = CScript([OP_DROP, OP_TRUE])
tx1 = create_transaction(
coinbases[0],
n=0,
sig=CScript([OP_TRUE]),
out=scriptpubkey,
value=coinbases[0].vout[0].n_value - 1000,
)
pad_tx(tx1)
tx2 = create_transaction(
tx1,
n=0,
sig=CScript([b"FILTERME"]),
out=scriptpubkey,
value=tx1.vout[0].n_value - 1000,
)
pad_tx(tx2)
n = self.nodes[0]
mempool = await cli.call("mempool.get")
assert_equal(0, len(mempool["transactions"]))
tx1_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx1.to_hex()))
tx2_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx2.to_hex()))
await self.wait_for_mempool_count(cli, count=2)
mempool = await cli.call(
"mempool.get", {"scriptsig": to_hex(b"FILTERME").decode("ascii")}
)
print(mempool)
assert_equal(1, len(mempool["transactions"]))
assert tx1_id not in mempool["transactions"]
assert tx2_id in mempool["transactions"]
await self.mine_blocks(cli, n, 1, [tx1, tx2])
async def test_scriptpubkey_filter(self, cli, n, utxos):
scriptpubkey1 = CScript([OP_DROP, OP_TRUE])
scriptpubkey2 = CScript([OP_DEPTH])
tx1 = create_transaction(
utxos[0],
n=0,
sig=CScript([OP_TRUE]),
out=scriptpubkey1,
value=utxos[0].vout[0].n_value - 1000,
)
pad_tx(tx1)
tx2 = create_transaction(
tx1,
n=0,
sig=CScript([b"FILTERME"]),
out=scriptpubkey2,
value=tx1.vout[0].n_value - 1000,
)
pad_tx(tx2)
n = self.nodes[0]
mempool = await cli.call("mempool.get")
assert_equal(0, len(mempool["transactions"]))
tx1_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx1.to_hex()))
tx2_id = await get_txid_from_idem(n, await cli.call(TX_BROADCAST, tx2.to_hex()))
await self.wait_for_mempool_count(cli, count=2)
mempool = await cli.call("mempool.get", {"scriptpubkey": scriptpubkey1.hex()})
assert_equal(1, len(mempool["transactions"]))
assert tx1_id in mempool["transactions"]
assert tx2_id not in mempool["transactions"]
both_filter = {
"scriptpubkey": scriptpubkey1.hex(),
"scriptsig": to_hex(b"FILTERME").decode("ascii"),
}
both_filter["operation"] = "union"
mempool = await cli.call("mempool.get", both_filter)
assert_equal(2, len(mempool["transactions"]))
both_filter["operation"] = "except"
mempool = await cli.call("mempool.get", both_filter)
assert_equal(0, len(mempool["transactions"]))
del both_filter["operation"]
mempool = await cli.call("mempool.get", both_filter)
assert_equal(0, len(mempool["transactions"]))
both_filter = {
"scriptpubkey": scriptpubkey2.hex(),
"scriptsig": to_hex(b"FILTERME").decode("ascii"),
"operation": "except",
}
mempool = await cli.call("mempool.get", both_filter)
print(mempool)
assert_equal(1, len(mempool["transactions"]))
assert tx2_id in mempool["transactions"]
await self.mine_blocks(cli, n, 1, [tx1, tx2])
if __name__ == "__main__":
asyncio.run(ElectrumUtxoTests().main())