Skip to content

Commit

Permalink
MWEB: Functional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBurkett committed Jan 30, 2022
1 parent bc9dc94 commit ca9b2ca
Show file tree
Hide file tree
Showing 23 changed files with 389 additions and 34 deletions.
6 changes: 5 additions & 1 deletion test/functional/feature_bip68_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ def set_test_params(self):
[
"-acceptnonstdtxn=1",
"-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=0",
"-vbparams=mweb:-2:0",
],
["-acceptnonstdtxn=0"],
]

def skip_test_if_missing_module(self):
Expand Down
1 change: 1 addition & 0 deletions test/functional/feature_cltv.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def set_test_params(self):
'[email protected]',
'-par=1', # Use only one script thread to get the exact reject reason for testing
'-acceptnonstdtxn=1', # cltv_invalidate is nonstandard
'-vbparams=mweb:-2:0',
]]
self.setup_clean_chain = True
self.rpc_timeout = 480
Expand Down
1 change: 1 addition & 0 deletions test/functional/feature_dersig.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def set_test_params(self):
self.extra_args = [[
'[email protected]',
'-par=1', # Use only one script thread to get the exact log msg for testing
'-vbparams=mweb:-2:0',
]]
self.setup_clean_chain = True
self.rpc_timeout = 240
Expand Down
6 changes: 3 additions & 3 deletions test/functional/feature_maxuploadtarget.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [[
"-maxuploadtarget=800",
"-maxuploadtarget=3200",
"-acceptnonstdtxn=1",
"-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
]]
Expand Down Expand Up @@ -90,8 +90,8 @@ def run_test(self):
getdata_request = msg_getdata()
getdata_request.inv.append(CInv(MSG_BLOCK, big_old_block))

max_bytes_per_day = 800*1024*1024
daily_buffer = 144 * 4000000
max_bytes_per_day = 3200*1024*1024
daily_buffer = 144 * 4000000 * 4 # MWEB uses a buffer 4x the max serialized segwit block
max_bytes_available = max_bytes_per_day - daily_buffer
success_count = max_bytes_available // old_block_size

Expand Down
1 change: 1 addition & 0 deletions test/functional/feature_nulldummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def set_test_params(self):
self.extra_args = [[
'-segwitheight=432',
'-addresstype=legacy',
'-vbparams=mweb:-2:0',
]] * 2

def skip_test_if_missing_module(self):
Expand Down
3 changes: 3 additions & 0 deletions test/functional/feature_segwit.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,20 @@ def set_test_params(self):
"-rpcserialversion=0",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=1",
"-rpcserialversion=1",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
[
"-acceptnonstdtxn=1",
"-segwitheight=432",
"-addresstype=legacy",
"-vbparams=mweb:-2:0",
],
]
self.rpc_timeout = 120
Expand Down
109 changes: 109 additions & 0 deletions test/functional/mweb_basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Basic MWEB test"""

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal

class MWEBBasicTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

def run_test(self):
self.log.info("Create all pre-MWEB blocks")
self.nodes[0].generate(431)

self.log.info("Pegin some coins")
addr0 = self.nodes[0].getnewaddress(address_type='mweb')
self.nodes[0].sendtoaddress(addr0, 10)

self.log.info("Create some blocks - activate MWEB")
self.nodes[0].generate(10)
self.sync_all()

self.log.info("Check for MWEB UTXOs")
utxos = [x for x in self.nodes[0].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 2)
utxos.sort(key=lambda x: x['amount'])

utxo0 = utxos[0]
utxo1 = utxos[1]
if utxos[0]['address'] != addr0:
utxo0 = utxos[1]
utxo1 = utxos[0]

assert utxo0['amount'] == 10 and utxo0['address'] == addr0
assert 2 < utxo1['amount'] < 2.5 # change from single 12.5 LTC coinbase being spent

self.log.info("Send MWEB coins to node 1")
addr1 = self.nodes[1].getnewaddress(address_type='mweb')
tx1_hash = self.nodes[0].sendtoaddress(addr1, 5)
tx1 = self.nodes[0].getmempoolentry(tx1_hash)
self.log.info("tx1: {}".format(tx1))
self.nodes[0].generate(1)
self.sync_all()

self.log.info("Check MWEB coins are spent on node 0")
utxos = [x for x in self.nodes[0].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 2)
assert sum(x['amount'] for x in utxos) < 45

self.log.info("Check for MWEB UTXO on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 5 and utxos[0]['address'] == addr1

self.log.info("Send MWEB coins to node 0")
self.nodes[1].sendtoaddress(addr0, 2)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()

self.log.info("Check MWEB coins are spent on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert sum(x['amount'] for x in utxos) < 3
self.log.info("UTXO amount: {}".format(utxos[0]['amount']))

self.log.info("Check for MWEB UTXO on node 0")
utxos = self.nodes[0].listunspent(addresses=[addr0])
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 2 and utxos[0]['address'] == addr0

self.log.info("Pegout coins on node 1")
addr2 = self.nodes[1].getnewaddress()
self.nodes[1].sendtoaddress(addr2, 2)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()

self.log.info("Check MWEB coins are spent on node 1")
utxos = [x for x in self.nodes[1].listunspent() if x['address'].startswith('tmweb')]
assert_equal(len(utxos), 1)
assert sum(x['amount'] for x in utxos) < 1

self.log.info("Mine 5 blocks. Peg-out maturity is 6 blocks, so coins shouldn't be available yet.")
self.nodes[1].generate(5)
self.sync_all()

self.log.info("Check for UTXO on node 1")
utxos = self.nodes[1].listunspent(addresses=[addr2])
assert_equal(len(utxos), 0)

self.log.info("Mine 1 more block. Peg-out coins should mature.")
self.nodes[1].generate(1)
self.sync_all()

self.log.info("Check for UTXO on node 1")
utxos = self.nodes[1].listunspent(addresses=[addr2])
assert_equal(len(utxos), 1)
assert utxos[0]['amount'] == 2 and utxos[0]['address'] == addr2

if __name__ == '__main__':
MWEBBasicTest().main()
39 changes: 39 additions & 0 deletions test/functional/mweb_pegout_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Verify that we can pegout all coins in the MWEB"""

from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
from test_framework.ltc_util import get_hog_addr_txout, setup_mweb_chain

class MWEBPegoutAllTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

def run_test(self):
self.log.info("Setup MWEB chain")
setup_mweb_chain(self.nodes[0])

total_balance = self.nodes[0].getbalance()
pegout_txid = self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=total_balance, subtractfeefromamount=True)
pegout_tx = self.nodes[0].gettransaction(txid=pegout_txid, verbose=True)
assert_equal(len(self.nodes[0].getrawmempool()), 1)
self.nodes[0].generate(1)
assert_equal(len(self.nodes[0].getrawmempool()), 0)

self.log.info("Check that pegged in amount is 0")
hog_addr_txout = get_hog_addr_txout(self.nodes[0])
assert_equal(hog_addr_txout.nValue, 0.0)

self.log.info("Ensure we can mine the next block")
self.nodes[0].generate(1)

if __name__ == '__main__':
MWEBPegoutAllTest().main()
65 changes: 65 additions & 0 deletions test/functional/mweb_reorg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
# Copyright (c) 2014-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test mempool re-org scenarios for MWEB transactions
Test re-org scenarios with a mempool that contains transactions
that create or spend (directly or indirectly) MWEB outputs.
"""

import json

from test_framework.blocktools import create_raw_transaction
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error
from test_framework.ltc_util import setup_mweb_chain

class MWEBReorgTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [
[
'[email protected]', # immediate tx relay
],
[]
]

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

def run_test(self):
self.basic_reorg_test()

def basic_reorg_test(self):
self.log.info("Create all pre-MWEB blocks")
setup_mweb_chain(self.nodes[0])

self.log.info("Pegin some coins in pegin_tx1. pegin_tx1 should be in the mempool")
node0_mweb_addr = self.nodes[0].getnewaddress(address_type='mweb')
pegin_tx1_id = self.nodes[0].sendtoaddress(node0_mweb_addr, 100)
self.sync_all()

assert_equal(set(self.nodes[1].getrawmempool()), {pegin_tx1_id})

self.log.info("Mine pegin_tx1 in block0a, and mine a few blocks on top. mempool should be empty")
block0a = self.nodes[0].generate(4)[0]
self.sync_all()

assert_equal(len(self.nodes[1].getrawmempool()), 0)

self.log.info("Invalidate block0a. pegin_tx1 should be back in the mempool")
self.nodes[1].invalidateblock(block0a)
assert_equal(set(self.nodes[1].getrawmempool()), {pegin_tx1_id})

self.log.info("Generate block0b. pegin_tx1 should be included in the block")
block0b_hash = self.nodes[1].generate(1)[0]

block0b_txs = self.nodes[1].getblock(block0b_hash, 2)['tx']
assert_equal(len(block0b_txs), 3)
assert_equal(block0b_txs[1]['txid'], pegin_tx1_id)


if __name__ == '__main__':
MWEBReorgTest().main()
80 changes: 80 additions & 0 deletions test/functional/mweb_weight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
# Copyright (c) 2021 The Litecoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""MWEB block weight test"""

from decimal import Decimal

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal

class MWEBWeightTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.rpc_timeout = 120
self.num_nodes = 3
self.extra_args = [["-spendzeroconfchange=0"]] * self.num_nodes

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

def run_test(self):
self.log.info("Create some blocks")
self.nodes[0].generate(101)

self.log.info("Pegin some coins - activate MWEB")
addr = self.nodes[0].getnewaddress(address_type='mweb')
self.nodes[0].sendtoaddress(addr, 1)
self.sync_all()
self.nodes[1].generate(700)
self.sync_all()

# Workaround for syncing issue
self.nodes[2].generate(1)
self.sync_all()

self.nodes[2].generate(700)
self.sync_all()

# Max number of MWEB transactions in a block (21000/39)
tx_limit = 538

self.log.info("Create transactions up to the max block weight")
addr = self.nodes[0].getnewaddress(address_type='mweb')
for x in range(0, tx_limit):
self.nodes[1].sendtoaddress(addr, 1)
assert_equal(len(self.nodes[1].getrawmempool()), tx_limit)

self.log.info("Create a block")
self.nodes[1].generate(1)
self.sync_all()

self.log.info("Check mempool is empty")
assert_equal(len(self.nodes[1].getrawmempool()), 0)

self.log.info("Check UTXOs have matured")
utxos = self.nodes[0].listunspent(addresses=[addr])
assert_equal(len(utxos), tx_limit)
assert all(x['amount'] == 1 and x['spendable'] for x in utxos)

self.log.info("Create transactions exceeding the max block weight")
addr = self.nodes[0].getnewaddress(address_type='mweb')
for x in range(0, tx_limit + 1):
self.nodes[2].sendtoaddress(addr, 0.01)
assert_equal(len(self.nodes[2].getrawmempool()), tx_limit + 1)

self.log.info("Create a block")
self.nodes[2].generate(1)
self.sync_all()

self.log.info("Check mempool is not empty")
assert_equal(len(self.nodes[2].getrawmempool()), 1)

self.log.info("Check UTXOs have matured")
utxos = self.nodes[0].listunspent(addresses=[addr])
assert_equal(len(utxos), tx_limit)
assert all(x['amount'] == Decimal('0.01') and x['spendable'] for x in utxos)

if __name__ == '__main__':
MWEBWeightTest().main()
4 changes: 2 additions & 2 deletions test/functional/p2p_blockfilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ def set_test_params(self):
self.rpc_timeout = 480
self.num_nodes = 2
self.extra_args = [
["-blockfilterindex", "-peerblockfilters"],
["-blockfilterindex"],
["-blockfilterindex", "-peerblockfilters", "-vbparams=mweb:-2:0"],
["-blockfilterindex", "-vbparams=mweb:-2:0"],
]

def run_test(self):
Expand Down
1 change: 1 addition & 0 deletions test/functional/p2p_compactblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def set_test_params(self):
self.num_nodes = 1
self.extra_args = [[
"-acceptnonstdtxn=1",
"-vbparams=mweb:-2:0",
]]
self.utxos = []

Expand Down
Loading

0 comments on commit ca9b2ca

Please sign in to comment.