mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
test: Various test improvements (#5382)
## Issue being fixed or feature implemented Speed thing up:8075fc0c61
Unify things:ff1a390224
(and _probably_ fix issues like https://gitlab.com/dashpay/dash/-/jobs/4304343867),876f5c3a9f
,ed58cdda13
Let tsan tests finish on smaller/slower machines:ba1e3360f9
## What was done? pls see individual commits ## How Has This Been Tested? run tests locally and my in gitlab ci https://gitlab.com/UdjinM6/dash/-/jobs/4319419014 ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_
This commit is contained in:
parent
6e75f5b2a5
commit
3d77c539d2
@ -13,16 +13,15 @@ Checks intra quorum connections
|
||||
import time
|
||||
|
||||
from test_framework.test_framework import DashTestFramework
|
||||
from test_framework.util import assert_greater_than_or_equal, Options, wait_until
|
||||
|
||||
# Probes should age after this many seconds.
|
||||
# NOTE: mine_quorum() can bump mocktime quite often internally so make sure this number is high enough.
|
||||
MAX_AGE = 120 * Options.timeout_scale
|
||||
from test_framework.util import assert_greater_than_or_equal, wait_until
|
||||
|
||||
class LLMQConnections(DashTestFramework):
|
||||
def set_test_params(self):
|
||||
self.set_dash_test_params(15, 14, fast_dip3_enforcement=True)
|
||||
self.set_dash_llmq_test_params(5, 3)
|
||||
# Probes should age after this many seconds.
|
||||
# NOTE: mine_quorum() can bump mocktime quite often internally so make sure this number is high enough.
|
||||
self.MAX_AGE = int(120 * self.options.timeout_factor)
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0)
|
||||
@ -57,7 +56,7 @@ class LLMQConnections(DashTestFramework):
|
||||
wait_until(lambda: self.get_mn_probe_count(mn.node, q, False) == 4)
|
||||
|
||||
self.log.info("checking that probes age")
|
||||
self.bump_mocktime(MAX_AGE)
|
||||
self.bump_mocktime(self.MAX_AGE)
|
||||
for mn in self.get_quorum_masternodes(q):
|
||||
wait_until(lambda: self.get_mn_probe_count(mn.node, q, False) == 0)
|
||||
|
||||
@ -147,7 +146,7 @@ class LLMQConnections(DashTestFramework):
|
||||
peerMap[p['verified_proregtx_hash']] = p
|
||||
for mn in self.get_quorum_masternodes(q):
|
||||
pi = mnMap[mn.proTxHash]
|
||||
if pi['metaInfo']['lastOutboundSuccessElapsed'] < MAX_AGE:
|
||||
if pi['metaInfo']['lastOutboundSuccessElapsed'] < self.MAX_AGE:
|
||||
count += 1
|
||||
elif check_peers and mn.proTxHash in peerMap:
|
||||
count += 1
|
||||
|
@ -27,7 +27,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
self.extra_args = [['-usehd=0']] * self.num_nodes
|
||||
self.extra_args = [[f'-usehd={self.options.usehd}']] * self.num_nodes
|
||||
# This test isn't testing tx relay. Set whitelist on the peers for
|
||||
# instant tx relay.
|
||||
self.extra_args = [['-whitelist=noban@127.0.0.1']] * self.num_nodes
|
||||
@ -35,6 +35,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def add_options(self, parser):
|
||||
parser.add_argument("--usehd", dest="usehd", default=False, action="store_true",
|
||||
help="Test with -usehd enabled")
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
|
||||
|
@ -1,623 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_greater_than
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
self.extra_args = [['-usehd=1']] * self.num_nodes
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
super().setup_network()
|
||||
self.connect_nodes(0,1)
|
||||
self.connect_nodes(1,2)
|
||||
self.connect_nodes(0,2)
|
||||
self.connect_nodes(0,3)
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Mining blocks...")
|
||||
|
||||
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
# This test is not meant to test fee estimation and we'd like
|
||||
# to be sure all txs are sent at a consistent desired feerate
|
||||
for node in self.nodes:
|
||||
node.settxfee(min_relay_tx_fee)
|
||||
|
||||
# if the fee's positive delta is higher than this value tests will fail,
|
||||
# neg. delta always fail the tests.
|
||||
# The size of the signature of every input may be at most 2 bytes larger
|
||||
# than a minimum sized signature.
|
||||
|
||||
# = 2 bytes * minRelayTxFeePerByte
|
||||
feeTolerance = 2 * min_relay_tx_fee/1000
|
||||
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(121)
|
||||
self.sync_all()
|
||||
|
||||
watchonly_address = self.nodes[0].getnewaddress()
|
||||
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
|
||||
watchonly_amount = Decimal(2000)
|
||||
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
||||
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
||||
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 15)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 50)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
###############
|
||||
# simple test #
|
||||
###############
|
||||
inputs = [ ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 10 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
assert len(dec_tx['vin']) > 0 #test if we have enough inputs
|
||||
|
||||
##############################
|
||||
# simple test with two coins #
|
||||
##############################
|
||||
inputs = [ ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 22 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
assert len(dec_tx['vin']) > 0 #test if we have enough inputs
|
||||
|
||||
##############################
|
||||
# simple test with two coins #
|
||||
##############################
|
||||
inputs = [ ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 26 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
assert len(dec_tx['vin']) > 0
|
||||
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
|
||||
|
||||
|
||||
################################
|
||||
# simple test with two outputs #
|
||||
################################
|
||||
inputs = [ ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 26, self.nodes[1].getnewaddress() : 25 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
for out in dec_tx['vout']:
|
||||
totalOut += out['value']
|
||||
|
||||
assert len(dec_tx['vin']) > 0
|
||||
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
|
||||
|
||||
|
||||
#########################################################################
|
||||
# test a fundrawtransaction with a VIN greater than the required amount #
|
||||
#########################################################################
|
||||
utx = False
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 50:
|
||||
utx = aUtx
|
||||
break
|
||||
|
||||
assert utx!=False
|
||||
|
||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||
outputs = { self.nodes[0].getnewaddress() : 10 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
for out in dec_tx['vout']:
|
||||
totalOut += out['value']
|
||||
|
||||
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
|
||||
|
||||
|
||||
#####################################################################
|
||||
# test a fundrawtransaction with which will not get a change output #
|
||||
#####################################################################
|
||||
utx = False
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 50:
|
||||
utx = aUtx
|
||||
break
|
||||
|
||||
assert utx!=False
|
||||
|
||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||
outputs = { self.nodes[0].getnewaddress() : Decimal(50) - fee - feeTolerance }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
for out in dec_tx['vout']:
|
||||
totalOut += out['value']
|
||||
|
||||
assert_equal(rawtxfund['changepos'], -1)
|
||||
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
|
||||
|
||||
|
||||
#########################################################################
|
||||
# test a fundrawtransaction with a VIN smaller than the required amount #
|
||||
#########################################################################
|
||||
utx = False
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 10:
|
||||
utx = aUtx
|
||||
break
|
||||
|
||||
assert utx!=False
|
||||
|
||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
|
||||
outputs = { self.nodes[0].getnewaddress() : 10 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
|
||||
# 4-byte version + 1-byte vin count + 36-byte prevout then script_len
|
||||
rawtx = rawtx[:82] + "0100" + rawtx[84:]
|
||||
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
matchingOuts = 0
|
||||
for i, out in enumerate(dec_tx['vout']):
|
||||
totalOut += out['value']
|
||||
if out['scriptPubKey']['addresses'][0] in outputs:
|
||||
matchingOuts+=1
|
||||
else:
|
||||
assert_equal(i, rawtxfund['changepos'])
|
||||
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])
|
||||
|
||||
assert_equal(matchingOuts, 1)
|
||||
assert_equal(len(dec_tx['vout']), 2)
|
||||
|
||||
|
||||
###########################################
|
||||
# test a fundrawtransaction with two VINs #
|
||||
###########################################
|
||||
utx = False
|
||||
utx2 = False
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 10:
|
||||
utx = aUtx
|
||||
if aUtx['amount'] == 50:
|
||||
utx2 = aUtx
|
||||
|
||||
|
||||
assert utx!=False
|
||||
|
||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 60 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
matchingOuts = 0
|
||||
for out in dec_tx['vout']:
|
||||
totalOut += out['value']
|
||||
if out['scriptPubKey']['addresses'][0] in outputs:
|
||||
matchingOuts+=1
|
||||
|
||||
assert_equal(matchingOuts, 1)
|
||||
assert_equal(len(dec_tx['vout']), 2)
|
||||
|
||||
matchingIns = 0
|
||||
for vinOut in dec_tx['vin']:
|
||||
for vinIn in inputs:
|
||||
if vinIn['txid'] == vinOut['txid']:
|
||||
matchingIns+=1
|
||||
|
||||
assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params
|
||||
|
||||
#########################################################
|
||||
# test a fundrawtransaction with two VINs and two vOUTs #
|
||||
#########################################################
|
||||
utx = False
|
||||
utx2 = False
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 10:
|
||||
utx = aUtx
|
||||
if aUtx['amount'] == 50:
|
||||
utx2 = aUtx
|
||||
|
||||
|
||||
assert utx!=False
|
||||
|
||||
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
|
||||
outputs = { self.nodes[0].getnewaddress() : 60, self.nodes[0].getnewaddress() : 10 }
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
fee = rawtxfund['fee']
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
totalOut = 0
|
||||
matchingOuts = 0
|
||||
for out in dec_tx['vout']:
|
||||
totalOut += out['value']
|
||||
if out['scriptPubKey']['addresses'][0] in outputs:
|
||||
matchingOuts+=1
|
||||
|
||||
assert_equal(matchingOuts, 2)
|
||||
assert_equal(len(dec_tx['vout']), 3)
|
||||
|
||||
##############################################
|
||||
# test a fundrawtransaction with invalid vin #
|
||||
##############################################
|
||||
listunspent = self.nodes[2].listunspent()
|
||||
inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
|
||||
outputs = { self.nodes[0].getnewaddress() : 10}
|
||||
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
|
||||
try:
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
raise AssertionError("Spent more than available")
|
||||
except JSONRPCException as e:
|
||||
assert "Insufficient" in e.error['message']
|
||||
|
||||
|
||||
############################################################
|
||||
#compare fee of a standard pubkeyhash transaction
|
||||
inputs = []
|
||||
outputs = {self.nodes[1].getnewaddress():11}
|
||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 11)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert feeDelta >= 0 and feeDelta <= feeTolerance
|
||||
############################################################
|
||||
|
||||
############################################################
|
||||
#compare fee of a standard pubkeyhash transaction with multiple outputs
|
||||
inputs = []
|
||||
outputs = {self.nodes[1].getnewaddress():11,self.nodes[1].getnewaddress():12,self.nodes[1].getnewaddress():1,self.nodes[1].getnewaddress():13,self.nodes[1].getnewaddress():2,self.nodes[1].getnewaddress():3}
|
||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendmany("", outputs)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert feeDelta >= 0 and feeDelta <= feeTolerance
|
||||
############################################################
|
||||
|
||||
|
||||
############################################################
|
||||
#compare fee of a 2of2 multisig p2sh transaction
|
||||
|
||||
# create 2of2 addr
|
||||
addr1 = self.nodes[1].getnewaddress()
|
||||
addr2 = self.nodes[1].getnewaddress()
|
||||
|
||||
addr1Obj = self.nodes[1].getaddressinfo(addr1)
|
||||
addr2Obj = self.nodes[1].getaddressinfo(addr2)
|
||||
|
||||
mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
|
||||
inputs = []
|
||||
outputs = {mSigObj:11}
|
||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 11)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert feeDelta >= 0 and feeDelta <= feeTolerance
|
||||
############################################################
|
||||
|
||||
|
||||
############################################################
|
||||
#compare fee of a standard pubkeyhash transaction
|
||||
|
||||
# create 4of5 addr
|
||||
addr1 = self.nodes[1].getnewaddress()
|
||||
addr2 = self.nodes[1].getnewaddress()
|
||||
addr3 = self.nodes[1].getnewaddress()
|
||||
addr4 = self.nodes[1].getnewaddress()
|
||||
addr5 = self.nodes[1].getnewaddress()
|
||||
|
||||
addr1Obj = self.nodes[1].getaddressinfo(addr1)
|
||||
addr2Obj = self.nodes[1].getaddressinfo(addr2)
|
||||
addr3Obj = self.nodes[1].getaddressinfo(addr3)
|
||||
addr4Obj = self.nodes[1].getaddressinfo(addr4)
|
||||
addr5Obj = self.nodes[1].getaddressinfo(addr5)
|
||||
|
||||
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']
|
||||
|
||||
inputs = []
|
||||
outputs = {mSigObj:11}
|
||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 11)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert feeDelta >= 0 and feeDelta <= feeTolerance
|
||||
############################################################
|
||||
|
||||
|
||||
############################################################
|
||||
# spend a 2of2 multisig transaction over fundraw
|
||||
|
||||
# create 2of2 addr
|
||||
addr1 = self.nodes[2].getnewaddress()
|
||||
addr2 = self.nodes[2].getnewaddress()
|
||||
|
||||
addr1Obj = self.nodes[2].getaddressinfo(addr1)
|
||||
addr2Obj = self.nodes[2].getaddressinfo(addr2)
|
||||
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
|
||||
|
||||
|
||||
# send 12 DASH to msig addr
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 12)
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
oldBalance = self.nodes[1].getbalance()
|
||||
inputs = []
|
||||
outputs = {self.nodes[1].getnewaddress():11}
|
||||
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[2].fundrawtransaction(rawTx)
|
||||
|
||||
signedTx = self.nodes[2].signrawtransactionwithwallet(fundedTx['hex'])
|
||||
txId = self.nodes[2].sendrawtransaction(signedTx['hex'])
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# make sure funds are received at node1
|
||||
assert_equal(oldBalance+Decimal('11.0000000'), self.nodes[1].getbalance())
|
||||
|
||||
############################################################
|
||||
# locked wallet test
|
||||
self.nodes[1].encryptwallet("test")
|
||||
self.stop_nodes()
|
||||
|
||||
self.start_nodes()
|
||||
# This test is not meant to test fee estimation and we'd like
|
||||
# to be sure all txs are sent at a consistent desired feerate
|
||||
for node in self.nodes:
|
||||
node.settxfee(min_relay_tx_fee)
|
||||
|
||||
self.connect_nodes(0,1)
|
||||
self.connect_nodes(1,2)
|
||||
self.connect_nodes(0,2)
|
||||
self.connect_nodes(0,3)
|
||||
self.sync_all()
|
||||
|
||||
# drain the keypool
|
||||
self.nodes[1].getnewaddress()
|
||||
self.nodes[1].getrawchangeaddress()
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():1.1}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
# fund a transaction that requires a new key for the change output
|
||||
# creating the key must be impossible because the wallet is locked
|
||||
try:
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
raise AssertionError("Wallet unlocked without passphrase")
|
||||
except JSONRPCException as e:
|
||||
assert 'Keypool ran out' in e.error['message']
|
||||
|
||||
#refill the keypool
|
||||
self.nodes[1].walletpassphrase("test", 100)
|
||||
self.nodes[1].keypoolrefill(2) #need to refill the keypool to get an internal change address
|
||||
self.nodes[1].walletlock()
|
||||
|
||||
try:
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 12)
|
||||
raise AssertionError("Wallet unlocked without passphrase")
|
||||
except JSONRPCException as e:
|
||||
assert 'walletpassphrase' in e.error['message']
|
||||
|
||||
oldBalance = self.nodes[0].getbalance()
|
||||
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():11}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
|
||||
#now we need to unlock
|
||||
self.nodes[1].walletpassphrase("test", 100)
|
||||
signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
|
||||
txId = self.nodes[1].sendrawtransaction(signedTx['hex'])
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
# make sure funds are received at node1
|
||||
assert_equal(oldBalance+Decimal('511.0000000'), self.nodes[0].getbalance())
|
||||
|
||||
|
||||
###############################################
|
||||
# multiple (~19) inputs tx test | Compare fee #
|
||||
###############################################
|
||||
|
||||
#empty node1, send some small coins from node0 to node1
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
for i in range(0,20):
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
#fund a tx with ~20 small inputs
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[1].sendmany("", outputs)
|
||||
signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert feeDelta >= 0 and feeDelta <= feeTolerance*19 #~19 inputs
|
||||
|
||||
|
||||
#############################################
|
||||
# multiple (~19) inputs tx test | sign/send #
|
||||
#############################################
|
||||
|
||||
#again, empty node1, send some small coins from node0 to node1
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
for i in range(0,20):
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
#fund a tx with ~20 small inputs
|
||||
oldBalance = self.nodes[0].getbalance()
|
||||
|
||||
inputs = []
|
||||
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
|
||||
rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
fundedAndSignedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
|
||||
txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex'])
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
assert_equal(oldBalance+Decimal('500.19000000'), self.nodes[0].getbalance()) #0.19+block reward
|
||||
|
||||
#####################################################
|
||||
# test fundrawtransaction with OP_RETURN and no vin #
|
||||
#####################################################
|
||||
|
||||
rawtx = "0100000000010000000000000000066a047465737400000000"
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
|
||||
|
||||
assert_equal(len(dec_tx['vin']), 0)
|
||||
assert_equal(len(dec_tx['vout']), 1)
|
||||
|
||||
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
|
||||
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
|
||||
|
||||
assert_greater_than(len(dec_tx['vin']), 0) # at least one vin
|
||||
assert_equal(len(dec_tx['vout']), 2) # one change output added
|
||||
|
||||
|
||||
##################################################
|
||||
# test a fundrawtransaction using only watchonly #
|
||||
##################################################
|
||||
|
||||
inputs = []
|
||||
outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2}
|
||||
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
||||
|
||||
result = self.nodes[3].fundrawtransaction(rawtx, True)
|
||||
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
|
||||
assert_equal(len(res_dec["vin"]), 1)
|
||||
assert_equal(res_dec["vin"][0]["txid"], watchonly_txid)
|
||||
|
||||
assert "fee" in result.keys()
|
||||
assert_greater_than(result["changepos"], -1)
|
||||
|
||||
###############################################################
|
||||
# test fundrawtransaction using the entirety of watched funds #
|
||||
###############################################################
|
||||
|
||||
inputs = []
|
||||
outputs = {self.nodes[2].getnewaddress() : watchonly_amount}
|
||||
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
|
||||
|
||||
result = self.nodes[3].fundrawtransaction(rawtx, True)
|
||||
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
|
||||
assert_equal(len(res_dec["vin"]), 2)
|
||||
assert res_dec["vin"][0]["txid"] == watchonly_txid or res_dec["vin"][1]["txid"] == watchonly_txid
|
||||
|
||||
assert_greater_than(result["fee"], 0)
|
||||
assert_greater_than(result["changepos"], -1)
|
||||
assert_equal(result["fee"] + res_dec["vout"][result["changepos"]]["value"], watchonly_amount / 10)
|
||||
|
||||
signedtx = self.nodes[3].signrawtransactionwithwallet(result["hex"])
|
||||
assert not signedtx["complete"]
|
||||
signedtx = self.nodes[0].signrawtransactionwithwallet(signedtx["hex"])
|
||||
assert signedtx["complete"]
|
||||
self.nodes[0].sendrawtransaction(signedtx["hex"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
RawTransactionsTest().main()
|
@ -49,7 +49,6 @@ from .util import (
|
||||
make_change,
|
||||
p2p_port,
|
||||
set_node_times,
|
||||
set_timeout_scale,
|
||||
satoshi_round,
|
||||
softfork_active,
|
||||
wait_until,
|
||||
@ -136,6 +135,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
self.requires_wallet = False
|
||||
self.set_test_params()
|
||||
assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes
|
||||
if self.options.timeout_scale != 1:
|
||||
print("DEPRECATED: --timeoutscale option is no longer available, please use --timeout-factor instead")
|
||||
if self.options.timeout_factor == 1:
|
||||
self.options.timeout_factor = self.options.timeout_scale
|
||||
if self.options.timeout_factor == 0 :
|
||||
self.options.timeout_factor = 99999
|
||||
self.rpc_timeout = int(self.rpc_timeout * self.options.timeout_factor) # optionally, increase timeout by a factor
|
||||
@ -200,7 +203,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
parser.add_argument("--dashd-arg", dest="dashd_extra_args", default=[], action="append",
|
||||
help="Pass extra args to all dashd instances")
|
||||
parser.add_argument("--timeoutscale", dest="timeout_scale", default=1, type=int,
|
||||
help="Scale the test timeouts by multiplying them with the here provided value (default: %(default)s)")
|
||||
help=argparse.SUPPRESS)
|
||||
parser.add_argument("--perf", dest="perf", default=False, action="store_true",
|
||||
help="profile running nodes with perf for the duration of the test")
|
||||
parser.add_argument("--valgrind", dest="valgrind", default=False, action="store_true",
|
||||
@ -227,11 +230,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
def setup(self):
|
||||
"""Call this method to start up the test framework object with options set."""
|
||||
|
||||
if self.options.timeout_scale < 1:
|
||||
raise RuntimeError("--timeoutscale can't be less than 1")
|
||||
|
||||
set_timeout_scale(self.options.timeout_scale)
|
||||
|
||||
PortSeed.n = self.options.port_seed
|
||||
|
||||
check_json_precision()
|
||||
@ -530,24 +528,38 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
self.nodes.append(t_node)
|
||||
return t_node
|
||||
|
||||
def dynamically_initialize_datadir(self, chain, node_p2p_port, node_rpc_port):
|
||||
data_dir = get_datadir_path(self.options.tmpdir, len(self.nodes))
|
||||
if not os.path.isdir(data_dir):
|
||||
os.makedirs(data_dir)
|
||||
def dynamically_initialize_datadir(self, node_p2p_port, node_rpc_port):
|
||||
source_data_dir = get_datadir_path(self.options.tmpdir, 0) # use node0 as a source
|
||||
new_data_dir = get_datadir_path(self.options.tmpdir, len(self.nodes))
|
||||
|
||||
# In general, it's a pretty bad idea to copy datadir folder on the fly...
|
||||
# But we flush all state changes to disk via gettxoutsetinfo call and
|
||||
# we don't care about wallets, so it works
|
||||
self.nodes[0].gettxoutsetinfo()
|
||||
shutil.copytree(source_data_dir, new_data_dir)
|
||||
|
||||
shutil.rmtree(os.path.join(new_data_dir, self.chain, 'wallets'))
|
||||
shutil.rmtree(os.path.join(new_data_dir, self.chain, 'llmq'))
|
||||
|
||||
for entry in os.listdir(os.path.join(new_data_dir, self.chain)):
|
||||
if entry not in ['chainstate', 'blocks', 'indexes', 'evodb']:
|
||||
os.remove(os.path.join(new_data_dir, self.chain, entry))
|
||||
|
||||
# Translate chain name to config name
|
||||
if chain == 'testnet3':
|
||||
if self.chain == 'testnet3':
|
||||
chain_name_conf_arg = 'testnet'
|
||||
chain_name_conf_section = 'test'
|
||||
chain_name_conf_arg_value = '1'
|
||||
elif chain == 'devnet':
|
||||
elif self.chain == 'devnet':
|
||||
chain_name_conf_arg = 'devnet'
|
||||
chain_name_conf_section = 'devnet'
|
||||
chain_name_conf_arg_value = 'devnet1'
|
||||
else:
|
||||
chain_name_conf_arg = chain
|
||||
chain_name_conf_section = chain
|
||||
chain_name_conf_arg = self.chain
|
||||
chain_name_conf_section = self.chain
|
||||
chain_name_conf_arg_value = '1'
|
||||
with open(os.path.join(data_dir, "dash.conf"), 'w', encoding='utf8') as f:
|
||||
|
||||
with open(os.path.join(new_data_dir, "dash.conf"), 'w', encoding='utf8') as f:
|
||||
f.write("{}={}\n".format(chain_name_conf_arg, chain_name_conf_arg_value))
|
||||
f.write("[{}]\n".format(chain_name_conf_section))
|
||||
f.write("port=" + str(node_p2p_port) + "\n")
|
||||
@ -561,8 +573,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
f.write("upnp=0\n")
|
||||
f.write("natpmp=0\n")
|
||||
f.write("shrinkdebugfile=0\n")
|
||||
os.makedirs(os.path.join(data_dir, 'stderr'), exist_ok=True)
|
||||
os.makedirs(os.path.join(data_dir, 'stdout'), exist_ok=True)
|
||||
os.makedirs(os.path.join(new_data_dir, 'stderr'), exist_ok=True)
|
||||
os.makedirs(os.path.join(new_data_dir, 'stdout'), exist_ok=True)
|
||||
|
||||
def start_node(self, i, *args, **kwargs):
|
||||
"""Start a dashd"""
|
||||
@ -695,7 +707,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
"""
|
||||
rpc_connections = nodes or self.nodes
|
||||
timeout = int(timeout * self.options.timeout_factor)
|
||||
timeout *= self.options.timeout_scale
|
||||
stop_time = time.time() + timeout
|
||||
while time.time() <= stop_time:
|
||||
best_hash = [x.getbestblockhash() for x in rpc_connections]
|
||||
@ -716,7 +727,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
"""
|
||||
rpc_connections = nodes or self.nodes
|
||||
timeout = int(timeout * self.options.timeout_factor)
|
||||
timeout *= self.options.timeout_scale
|
||||
stop_time = time.time() + timeout
|
||||
if self.mocktime != 0 and wait_func is None:
|
||||
wait_func = lambda: self.bump_mocktime(3, nodes=nodes)
|
||||
@ -1034,6 +1044,13 @@ class DashTestFramework(BitcoinTestFramework):
|
||||
|
||||
def activate_by_name(self, name, expected_activation_height=None):
|
||||
self.log.info("Wait for " + name + " activation")
|
||||
|
||||
# disable spork17 while mining blocks to activate "name" to prevent accidental quorum formation
|
||||
spork17_value = self.nodes[0].spork('show')['SPORK_17_QUORUM_DKG_ENABLED']
|
||||
self.bump_mocktime(1)
|
||||
self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 4070908800)
|
||||
self.wait_for_sporks_same()
|
||||
|
||||
# mine blocks in batches
|
||||
batch_size = 10
|
||||
if expected_activation_height is not None:
|
||||
@ -1063,20 +1080,14 @@ class DashTestFramework(BitcoinTestFramework):
|
||||
|
||||
assert softfork_active(self.nodes[0], name)
|
||||
|
||||
def activate_dip0024(self, expected_activation_height=None):
|
||||
# disable spork17 while mining blocks to activate dip0024 to prevent accidental quorum formation
|
||||
spork17_value = self.nodes[0].spork('show')['SPORK_17_QUORUM_DKG_ENABLED']
|
||||
self.bump_mocktime(1)
|
||||
self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 4070908800)
|
||||
self.wait_for_sporks_same()
|
||||
|
||||
self.activate_by_name('dip0024', expected_activation_height)
|
||||
|
||||
# revert spork17 changes
|
||||
self.bump_mocktime(1)
|
||||
self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", spork17_value)
|
||||
self.wait_for_sporks_same()
|
||||
|
||||
def activate_dip0024(self, expected_activation_height=None):
|
||||
self.activate_by_name('dip0024', expected_activation_height)
|
||||
|
||||
def activate_v19(self, expected_activation_height=None):
|
||||
self.activate_by_name('v19', expected_activation_height)
|
||||
|
||||
@ -1117,7 +1128,7 @@ class DashTestFramework(BitcoinTestFramework):
|
||||
# nothing to do
|
||||
return
|
||||
|
||||
self.dynamically_initialize_datadir(self.nodes[0].chain,node_p2p_port, node_rpc_port)
|
||||
self.dynamically_initialize_datadir(node_p2p_port, node_rpc_port)
|
||||
node_info = self.add_dynamically_node(self.extra_args[1])
|
||||
|
||||
args = ['-masternodeblsprivkey=%s' % created_mn_info.keyOperator] + node_info.extra_args
|
||||
|
@ -33,7 +33,6 @@ from .util import (
|
||||
wait_until,
|
||||
p2p_port,
|
||||
get_chain_folder,
|
||||
Options,
|
||||
EncodeDecimal,
|
||||
)
|
||||
|
||||
@ -79,7 +78,6 @@ class TestNode():
|
||||
self.stderr_dir = os.path.join(self.datadir, "stderr")
|
||||
self.rpchost = rpchost
|
||||
self.rpc_timeout = timewait
|
||||
self.rpc_timeout *= Options.timeout_scale
|
||||
self.binary = bitcoind
|
||||
self.coverage_dir = coverage_dir
|
||||
self.cwd = cwd
|
||||
|
@ -25,15 +25,6 @@ from io import BytesIO
|
||||
|
||||
logger = logging.getLogger("TestFramework.utils")
|
||||
|
||||
# Util options
|
||||
##############
|
||||
|
||||
class Options:
|
||||
timeout_scale = 1
|
||||
|
||||
def set_timeout_scale(_timeout_scale):
|
||||
Options.timeout_scale = _timeout_scale
|
||||
|
||||
# Assert functions
|
||||
##################
|
||||
|
||||
@ -225,7 +216,6 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), sleep=
|
||||
timeout = 60
|
||||
timeout = timeout * timeout_factor
|
||||
attempt = 0
|
||||
timeout *= Options.timeout_scale
|
||||
time_end = time.time() + timeout
|
||||
|
||||
while attempt < attempts and time.time() < time_end:
|
||||
|
@ -93,7 +93,7 @@ BASE_SCRIPTS = [
|
||||
'feature_maxuploadtarget.py',
|
||||
'feature_block.py', # NOTE: needs dash_hash to pass
|
||||
'rpc_fundrawtransaction.py',
|
||||
'rpc_fundrawtransaction_hd.py',
|
||||
'rpc_fundrawtransaction.py --usehd',
|
||||
'wallet_multiwallet.py --usecli',
|
||||
'p2p_quorum_data.py',
|
||||
# vv Tests less than 2m vv
|
||||
@ -471,7 +471,7 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, attempts=1, enab
|
||||
tmpdir=tmpdir,
|
||||
test_list=test_list,
|
||||
flags=flags,
|
||||
timeout_duration=30 * 60 if runs_ci else float('inf'), # in seconds
|
||||
timeout_duration= 90 * 60 if runs_ci else float('inf'), # in seconds
|
||||
use_term_control=use_term_control,
|
||||
attempts=attempts,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user