Initial Vexta Core v0.1.0 release
This commit is contained in:
commit
25c454329d
2481 changed files with 689289 additions and 0 deletions
149
test/functional/p2p_dandelion.py
Executable file
149
test/functional/p2p_dandelion.py
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2018 Bradley Denby
|
||||
# Distributed under the MIT software license. See the accompanying file COPYING
|
||||
# or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
"""Test transaction behaviors under the Dandelion spreading policy
|
||||
|
||||
Tests:
|
||||
1. Resistance to active probing:
|
||||
Stem: 0 --> 1 --> 2 --> 0 where each node has argument "-dandelion=1"
|
||||
Probe: TestNode --> 0
|
||||
Node 0 generates a Dandelion transaction "tx": 1.0 BTC from Node 0 to Node 2
|
||||
TestNode immediately sends getdata for tx to Node 0
|
||||
Assert that Node 0 does not reply with tx
|
||||
|
||||
2. Loop behavior:
|
||||
Stem: 0 --> 1 --> 2 --> 0 where each node has argument "-dandelion=1"
|
||||
Probe: TestNode --> 0
|
||||
Wait ~5 seconds after Test 1, then TestNode sends getdata for tx to Node 0
|
||||
Assert that Node 0 does not reply with tx
|
||||
|
||||
3. Resistance to black holes:
|
||||
Stem: 0 --> 1 --> 2 --> 0 where each node has argument "-dandelion=1"
|
||||
Probe: TestNode --> 0
|
||||
Wait ~45 seconds after Test 2, then TestNode sends getdata for tx to Node 0
|
||||
Assert that Node 0 replies with tx
|
||||
"""
|
||||
|
||||
from test_framework.p2p import P2PInterface
|
||||
from test_framework.test_framework import DigiByteTestFramework
|
||||
from test_framework.blocktools import COINBASE_MATURITY_2
|
||||
from test_framework.messages import (
|
||||
CTransaction,
|
||||
tx_from_hex,
|
||||
msg_getdata,
|
||||
CInv,
|
||||
)
|
||||
|
||||
import time # sleep
|
||||
|
||||
class TestP2PConn(P2PInterface):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def send_dandeliontx_getdata(self, dandeliontx_hash):
|
||||
msg = msg_getdata()
|
||||
msg.inv.append(CInv(5, dandeliontx_hash)) # 5: "DandelionTx"
|
||||
self.send_message(msg)
|
||||
|
||||
class DandelionTest(DigiByteTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
self.extra_args = []
|
||||
for i in range(self.num_nodes):
|
||||
self.extra_args.append(["-dandelion=1"]) # ,"-debug=dandelion","-printtoconsole=1"
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
# Tests 1,2,3: 0 --> 1 --> 2 --> 0
|
||||
self.connect_nodes(0, 1)
|
||||
self.connect_nodes(1, 2)
|
||||
self.connect_nodes(2, 0)
|
||||
|
||||
self.nodes[0].createwallet(wallet_name='w0', load_on_startup=True)
|
||||
self.nodes[1].createwallet(wallet_name='w1', load_on_startup=True)
|
||||
self.nodes[2].createwallet(wallet_name='w2', load_on_startup=True)
|
||||
|
||||
def run_test(self):
|
||||
# Convenience variables
|
||||
node0, node1, node2 = self.nodes
|
||||
w0 = node0.get_wallet_rpc('w0')
|
||||
w1 = node1.get_wallet_rpc('w1')
|
||||
w2 = node2.get_wallet_rpc('w2')
|
||||
|
||||
# Setup TestP2PConns
|
||||
test_node0 = node0.add_p2p_connection(TestP2PConn())
|
||||
|
||||
# Start networking thread
|
||||
test_node0.wait_for_verack()
|
||||
|
||||
# Get out of Initial Block Download (IBD)
|
||||
for node in self.nodes:
|
||||
self.generatetoaddress(node, 1, w0.getnewaddress(), sync_fun=self.no_op)
|
||||
|
||||
# Generate mature funds for node0 wallet
|
||||
self.generatetoaddress(node0, COINBASE_MATURITY_2 + 1, w0.getnewaddress())
|
||||
|
||||
# Tests 1,2,3
|
||||
# There is a low probability that one of these tests will fail even if
|
||||
# the implementation is correct. Thus, these tests are repeated upon
|
||||
# failure. A true bug will result in repeated failures.
|
||||
self.log.info('Starting tests...')
|
||||
test_1_passed = False
|
||||
test_2_passed = False
|
||||
test_3_passed = False
|
||||
tries_left = 5
|
||||
while(not (test_1_passed and test_2_passed and test_3_passed) and tries_left > 0):
|
||||
tries_left -= 1
|
||||
# Test 1: Resistance to active probing
|
||||
test_node0.message_count['notfound'] = 0
|
||||
node0_txid = node0.sendtoaddress(node2.getnewaddress(), 1.0)
|
||||
node0_tx = tx_from_hex(node0.gettransaction(node0_txid)['hex'])
|
||||
test_node0.send_dandeliontx_getdata(node0_tx.calc_sha256(True))
|
||||
time.sleep(1)
|
||||
|
||||
try:
|
||||
assert(test_node0.message_count['notfound']==1)
|
||||
if not test_1_passed:
|
||||
test_1_passed = True
|
||||
self.log.info('Success: resistance to active probing')
|
||||
except AssertionError:
|
||||
if not test_1_passed and tries_left == 0:
|
||||
self.log.info('Failed: resistance to active probing')
|
||||
|
||||
# Test 2: Loop behavior
|
||||
test_node0.message_count['notfound'] = 0
|
||||
time.sleep(3)
|
||||
test_node0.send_dandeliontx_getdata(node0_tx.calc_sha256(True))
|
||||
time.sleep(1)
|
||||
|
||||
try:
|
||||
assert(test_node0.message_count['notfound']==1)
|
||||
if not test_2_passed:
|
||||
test_2_passed = True
|
||||
self.log.info('Success: loop behavior')
|
||||
except AssertionError:
|
||||
if not test_2_passed and tries_left == 0:
|
||||
self.log.info('Failed: loop behavior')
|
||||
|
||||
# Test 3: Resistance to black holes
|
||||
test_node0.message_count['tx'] = 0
|
||||
time.sleep(44)
|
||||
test_node0.send_dandeliontx_getdata(node0_tx.calc_sha256(True))
|
||||
time.sleep(1)
|
||||
try:
|
||||
assert(test_node0.message_count['tx']==1)
|
||||
if not test_3_passed:
|
||||
test_3_passed = True
|
||||
self.log.info('Success: resistance to black holes')
|
||||
except AssertionError:
|
||||
if not test_3_passed and tries_left == 0:
|
||||
self.log.info('Failed: resistance to black holes')
|
||||
|
||||
all_tests_passed = test_1_passed and test_2_passed and test_3_passed
|
||||
assert(all_tests_passed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
DandelionTest().main()
|
||||
Loading…
Reference in a new issue