mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
re-activate transaction replacement functional test
This commit is contained in:
parent
92b5911234
commit
5af4d76f18
1 changed files with 45 additions and 40 deletions
|
|
@ -11,7 +11,6 @@ from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import *
|
||||||
from test_framework.script import *
|
from test_framework.script import *
|
||||||
from test_framework.mininode import *
|
from test_framework.mininode import *
|
||||||
|
|
||||||
MAX_REPLACEMENT_LIMIT = 100
|
MAX_REPLACEMENT_LIMIT = 100
|
||||||
|
|
||||||
def txToHex(tx):
|
def txToHex(tx):
|
||||||
|
|
@ -26,11 +25,8 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
|
||||||
unconfirmed otherwise.
|
unconfirmed otherwise.
|
||||||
"""
|
"""
|
||||||
fee = 1*COIN
|
fee = 1*COIN
|
||||||
while node.getbalance() < satoshi_round((amount + fee)/COIN):
|
|
||||||
node.generate(100)
|
|
||||||
#print (node.getbalance(), amount, fee)
|
|
||||||
|
|
||||||
new_addr = node.getnewaddress()
|
new_addr = node.validateaddress(node.getnewaddress())['unconfidential']
|
||||||
#print new_addr
|
#print new_addr
|
||||||
txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
|
txid = node.sendtoaddress(new_addr, satoshi_round((amount+fee)/COIN))
|
||||||
tx1 = node.getrawtransaction(txid, 1)
|
tx1 = node.getrawtransaction(txid, 1)
|
||||||
|
|
@ -39,14 +35,15 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
|
||||||
|
|
||||||
for i, txout in enumerate(tx1['vout']):
|
for i, txout in enumerate(tx1['vout']):
|
||||||
#print i, txout['scriptPubKey']['addresses']
|
#print i, txout['scriptPubKey']['addresses']
|
||||||
if txout['scriptPubKey']['addresses'] == [new_addr]:
|
if 'addresses' in txout['scriptPubKey'] and txout['scriptPubKey']['addresses'] == [new_addr]:
|
||||||
#print i
|
#print i
|
||||||
break
|
break
|
||||||
assert i is not None
|
assert i is not None
|
||||||
|
|
||||||
tx2 = CTransaction()
|
tx2 = CTransaction()
|
||||||
tx2.vin = [CTxIn(COutPoint(txid, i))]
|
tx2.vin = [CTxIn(COutPoint(txid, i))]
|
||||||
tx2.vout = [CTxOut(amount, scriptPubKey)]
|
tx2.vout = [CTxOut(amount, scriptPubKey), CTxOut(fee)]
|
||||||
|
tx2.vout = [CTxOut(amount, scriptPubKey), CTxOut(fee)]
|
||||||
tx2.rehash()
|
tx2.rehash()
|
||||||
|
|
||||||
signed_tx = node.signrawtransaction(txToHex(tx2))
|
signed_tx = node.signrawtransaction(txToHex(tx2))
|
||||||
|
|
@ -85,7 +82,6 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
self.is_network_split = False
|
self.is_network_split = False
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
return #TODO
|
|
||||||
make_utxo(self.nodes[0], 1*COIN)
|
make_utxo(self.nodes[0], 1*COIN)
|
||||||
|
|
||||||
print("Running test simple doublespend...")
|
print("Running test simple doublespend...")
|
||||||
|
|
@ -123,14 +119,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx1a = CTransaction()
|
tx1a = CTransaction()
|
||||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN), b'')]
|
||||||
tx1a_hex = txToHex(tx1a)
|
tx1a_hex = txToHex(tx1a)
|
||||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||||
|
|
||||||
# Should fail because we haven't changed the fee
|
# Should fail because we haven't changed the fee
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
|
tx1b.vout = [CTxOut(1*COIN, CScript([b'b'])), CTxOut(int(0.1*COIN), b'')]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -143,7 +139,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Extra 0.1 BTC fee
|
# Extra 0.1 BTC fee
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
|
tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b'])), CTxOut(int(0.2*COIN), b'')]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||||
|
|
||||||
|
|
@ -167,7 +163,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
remaining_value -= 1*COIN
|
remaining_value -= 1*COIN
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin = [CTxIn(prevout, nSequence=0)]
|
tx.vin = [CTxIn(prevout, nSequence=0)]
|
||||||
tx.vout = [CTxOut(remaining_value, CScript([1]))]
|
tx.vout = [CTxOut(remaining_value, CScript([1])), CTxOut(1*COIN)]
|
||||||
tx_hex = txToHex(tx)
|
tx_hex = txToHex(tx)
|
||||||
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
||||||
chain_txids.append(txid)
|
chain_txids.append(txid)
|
||||||
|
|
@ -177,7 +173,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# child fees - 40 BTC - so this attempt is rejected.
|
# child fees - 40 BTC - so this attempt is rejected.
|
||||||
dbl_tx = CTransaction()
|
dbl_tx = CTransaction()
|
||||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
|
dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1])), CTxOut(30*COIN)]
|
||||||
dbl_tx_hex = txToHex(dbl_tx)
|
dbl_tx_hex = txToHex(dbl_tx)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -190,7 +186,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Accepted with sufficient fee
|
# Accepted with sufficient fee
|
||||||
dbl_tx = CTransaction()
|
dbl_tx = CTransaction()
|
||||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
|
dbl_tx.vout = [CTxOut(1*COIN, CScript([1])), CTxOut(49*COIN)]
|
||||||
dbl_tx_hex = txToHex(dbl_tx)
|
dbl_tx_hex = txToHex(dbl_tx)
|
||||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||||
|
|
||||||
|
|
@ -200,27 +196,27 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
def test_doublespend_tree(self):
|
def test_doublespend_tree(self):
|
||||||
"""Doublespend of a big tree of transactions"""
|
"""Doublespend of a big tree of transactions"""
|
||||||
|
|
||||||
initial_nValue = 50*COIN
|
initial_nValue = 50*COIN
|
||||||
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
|
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
|
||||||
|
|
||||||
def branch(prevout, initial_value, max_txs, tree_width=5, fee=0.0001*COIN, _total_txs=None):
|
def branch(prevout, initial_value, max_txs, tree_width=5, fee=int(0.0001*COIN), _total_txs=None):
|
||||||
if _total_txs is None:
|
if _total_txs is None:
|
||||||
_total_txs = [0]
|
_total_txs = [0]
|
||||||
if _total_txs[0] >= max_txs:
|
if _total_txs[0] >= max_txs:
|
||||||
return
|
return
|
||||||
|
|
||||||
txout_value = (initial_value - fee) // tree_width
|
txout_value = (initial_value - fee) // tree_width
|
||||||
|
fee += (initial_value - fee) % tree_width
|
||||||
if txout_value < fee:
|
if txout_value < fee:
|
||||||
return
|
return
|
||||||
|
|
||||||
vout = [CTxOut(txout_value, CScript([i+1]))
|
vout = [CTxOut(txout_value, CScript([i+1]))
|
||||||
for i in range(tree_width)]
|
for i in range(tree_width)]
|
||||||
|
vout.append(CTxOut(int(fee)))
|
||||||
tx = CTransaction()
|
tx = CTransaction()
|
||||||
tx.vin = [CTxIn(prevout, nSequence=0)]
|
tx.vin = [CTxIn(prevout, nSequence=0)]
|
||||||
tx.vout = vout
|
tx.vout = vout
|
||||||
tx_hex = txToHex(tx)
|
tx_hex = txToHex(tx)
|
||||||
|
|
||||||
assert(len(tx.serialize()) < 100000)
|
assert(len(tx.serialize()) < 100000)
|
||||||
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
|
||||||
yield tx
|
yield tx
|
||||||
|
|
@ -229,6 +225,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
txid = int(txid, 16)
|
txid = int(txid, 16)
|
||||||
|
|
||||||
for i, txout in enumerate(tx.vout):
|
for i, txout in enumerate(tx.vout):
|
||||||
|
# Don't grab fee outputs
|
||||||
|
if i == len(tx.vout)-1:
|
||||||
|
continue
|
||||||
for x in branch(COutPoint(txid, i), txout_value,
|
for x in branch(COutPoint(txid, i), txout_value,
|
||||||
max_txs,
|
max_txs,
|
||||||
tree_width=tree_width, fee=fee,
|
tree_width=tree_width, fee=fee,
|
||||||
|
|
@ -243,7 +242,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Attempt double-spend, will fail because too little fee paid
|
# Attempt double-spend, will fail because too little fee paid
|
||||||
dbl_tx = CTransaction()
|
dbl_tx = CTransaction()
|
||||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
|
dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1])), CTxOut(fee*n)]
|
||||||
dbl_tx_hex = txToHex(dbl_tx)
|
dbl_tx_hex = txToHex(dbl_tx)
|
||||||
try:
|
try:
|
||||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||||
|
|
@ -255,7 +254,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# 1 BTC fee is enough
|
# 1 BTC fee is enough
|
||||||
dbl_tx = CTransaction()
|
dbl_tx = CTransaction()
|
||||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
|
dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1])), CTxOut(fee*n+1*COIN)]
|
||||||
dbl_tx_hex = txToHex(dbl_tx)
|
dbl_tx_hex = txToHex(dbl_tx)
|
||||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||||
|
|
||||||
|
|
@ -275,7 +274,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
dbl_tx = CTransaction()
|
dbl_tx = CTransaction()
|
||||||
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
|
dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1])), CTxOut(2*fee*n)]
|
||||||
dbl_tx_hex = txToHex(dbl_tx)
|
dbl_tx_hex = txToHex(dbl_tx)
|
||||||
try:
|
try:
|
||||||
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
|
||||||
|
|
@ -295,7 +294,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx1a = CTransaction()
|
tx1a = CTransaction()
|
||||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1a_hex = txToHex(tx1a)
|
tx1a_hex = txToHex(tx1a)
|
||||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||||
|
|
||||||
|
|
@ -303,7 +302,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# rejected.
|
# rejected.
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))]
|
tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000])), CTxOut(int(1.099*COIN))]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -320,7 +319,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx1a = CTransaction()
|
tx1a = CTransaction()
|
||||||
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
|
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
|
||||||
tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
|
tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1a_hex = txToHex(tx1a)
|
tx1a_hex = txToHex(tx1a)
|
||||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||||
|
|
||||||
|
|
@ -331,6 +330,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
|
tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
|
||||||
tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
|
tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
|
||||||
tx2.vout = tx1a.vout
|
tx2.vout = tx1a.vout
|
||||||
|
tx2.vout[-1] = CTxOut(int(1.9*COIN))
|
||||||
tx2_hex = txToHex(tx2)
|
tx2_hex = txToHex(tx2)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -343,7 +343,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Spend tx1a's output to test the indirect case.
|
# Spend tx1a's output to test the indirect case.
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
|
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1b.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||||
tx1b_txid = int(tx1b_txid, 16)
|
tx1b_txid = int(tx1b_txid, 16)
|
||||||
|
|
@ -368,13 +368,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx1 = CTransaction()
|
tx1 = CTransaction()
|
||||||
tx1.vin = [CTxIn(confirmed_utxo)]
|
tx1.vin = [CTxIn(confirmed_utxo)]
|
||||||
tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1_hex = txToHex(tx1)
|
tx1_hex = txToHex(tx1)
|
||||||
tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
|
tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
|
||||||
|
|
||||||
tx2 = CTransaction()
|
tx2 = CTransaction()
|
||||||
tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
|
tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
|
||||||
tx2.vout = tx1.vout
|
tx2.vout = tx1.vout
|
||||||
|
tx2.vout[-1] = CTxOut(int(0.2*COIN))
|
||||||
tx2_hex = txToHex(tx2)
|
tx2_hex = txToHex(tx2)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -394,10 +395,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
utxo = make_utxo(self.nodes[0], initial_nValue)
|
utxo = make_utxo(self.nodes[0], initial_nValue)
|
||||||
fee = int(0.0001*COIN)
|
fee = int(0.0001*COIN)
|
||||||
split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
|
split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
|
||||||
|
fee += int((initial_nValue-fee)%(MAX_REPLACEMENT_LIMIT+1))
|
||||||
|
|
||||||
outputs = []
|
outputs = []
|
||||||
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
||||||
outputs.append(CTxOut(split_value, CScript([1])))
|
outputs.append(CTxOut(split_value, CScript([1])))
|
||||||
|
outputs.append(CTxOut(fee))
|
||||||
|
|
||||||
splitting_tx = CTransaction()
|
splitting_tx = CTransaction()
|
||||||
splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
|
splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
|
||||||
|
|
@ -411,20 +414,22 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
||||||
tx_i = CTransaction()
|
tx_i = CTransaction()
|
||||||
tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
|
tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
|
||||||
tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
|
tx_i.vout = [CTxOut(split_value-fee, CScript([b'a'])), CTxOut(fee)]
|
||||||
tx_i_hex = txToHex(tx_i)
|
tx_i_hex = txToHex(tx_i)
|
||||||
self.nodes[0].sendrawtransaction(tx_i_hex, True)
|
self.nodes[0].sendrawtransaction(tx_i_hex, True)
|
||||||
|
|
||||||
# Now create doublespend of the whole lot; should fail.
|
# Now create doublespend of the whole lot; should fail.
|
||||||
# Need a big enough fee to cover all spending transactions and have
|
# Need a big enough fee to cover all spending transactions and have
|
||||||
# a higher fee rate
|
# a higher fee rate
|
||||||
double_spend_value = (split_value-100*fee)*(MAX_REPLACEMENT_LIMIT+1)
|
double_spend_fee = 100*fee*(MAX_REPLACEMENT_LIMIT+1)
|
||||||
|
double_spend_value = split_value*(MAX_REPLACEMENT_LIMIT+1)-double_spend_fee
|
||||||
inputs = []
|
inputs = []
|
||||||
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
for i in range(MAX_REPLACEMENT_LIMIT+1):
|
||||||
inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
|
inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
|
||||||
|
|
||||||
double_tx = CTransaction()
|
double_tx = CTransaction()
|
||||||
double_tx.vin = inputs
|
double_tx.vin = inputs
|
||||||
double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
|
double_tx.vout = [CTxOut(double_spend_value, CScript([b'a'])), CTxOut(double_spend_fee)]
|
||||||
double_tx_hex = txToHex(double_tx)
|
double_tx_hex = txToHex(double_tx)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -438,7 +443,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# If we remove an input, it should pass
|
# If we remove an input, it should pass
|
||||||
double_tx = CTransaction()
|
double_tx = CTransaction()
|
||||||
double_tx.vin = inputs[0:-1]
|
double_tx.vin = inputs[0:-1]
|
||||||
double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
|
double_tx.vout = [CTxOut(double_spend_value, CScript([b'a'])), CTxOut(double_spend_fee-split_value)]
|
||||||
double_tx_hex = txToHex(double_tx)
|
double_tx_hex = txToHex(double_tx)
|
||||||
self.nodes[0].sendrawtransaction(double_tx_hex, True)
|
self.nodes[0].sendrawtransaction(double_tx_hex, True)
|
||||||
|
|
||||||
|
|
@ -449,14 +454,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Create a non-opting in transaction
|
# Create a non-opting in transaction
|
||||||
tx1a = CTransaction()
|
tx1a = CTransaction()
|
||||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
|
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
|
||||||
tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1a_hex = txToHex(tx1a)
|
tx1a_hex = txToHex(tx1a)
|
||||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||||
|
|
||||||
# Shouldn't be able to double-spend
|
# Shouldn't be able to double-spend
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
|
tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b'])), CTxOut(int(0.2*COIN))]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -472,14 +477,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
# Create a different non-opting in transaction
|
# Create a different non-opting in transaction
|
||||||
tx2a = CTransaction()
|
tx2a = CTransaction()
|
||||||
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
|
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
|
||||||
tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx2a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx2a_hex = txToHex(tx2a)
|
tx2a_hex = txToHex(tx2a)
|
||||||
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
||||||
|
|
||||||
# Still shouldn't be able to double-spend
|
# Still shouldn't be able to double-spend
|
||||||
tx2b = CTransaction()
|
tx2b = CTransaction()
|
||||||
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||||
tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
|
tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b'])), CTxOut(int(0.2*COIN))]
|
||||||
tx2b_hex = txToHex(tx2b)
|
tx2b_hex = txToHex(tx2b)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -499,19 +504,19 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
tx3a = CTransaction()
|
tx3a = CTransaction()
|
||||||
tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
|
tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
|
||||||
CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
|
CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
|
||||||
tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
|
tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd'])), CTxOut(int(0.2*COIN))]
|
||||||
tx3a_hex = txToHex(tx3a)
|
tx3a_hex = txToHex(tx3a)
|
||||||
|
|
||||||
self.nodes[0].sendrawtransaction(tx3a_hex, True)
|
self.nodes[0].sendrawtransaction(tx3a_hex, True)
|
||||||
|
|
||||||
tx3b = CTransaction()
|
tx3b = CTransaction()
|
||||||
tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
|
tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
|
||||||
tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
|
tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e'])), CTxOut(int(0.5*COIN))]
|
||||||
tx3b_hex = txToHex(tx3b)
|
tx3b_hex = txToHex(tx3b)
|
||||||
|
|
||||||
tx3c = CTransaction()
|
tx3c = CTransaction()
|
||||||
tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
|
tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
|
||||||
tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
|
tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f'])), CTxOut(int(0.5*COIN))]
|
||||||
tx3c_hex = txToHex(tx3c)
|
tx3c_hex = txToHex(tx3c)
|
||||||
|
|
||||||
self.nodes[0].sendrawtransaction(tx3b_hex, True)
|
self.nodes[0].sendrawtransaction(tx3b_hex, True)
|
||||||
|
|
@ -528,14 +533,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx1a = CTransaction()
|
tx1a = CTransaction()
|
||||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx1a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx1a_hex = txToHex(tx1a)
|
tx1a_hex = txToHex(tx1a)
|
||||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||||
|
|
||||||
# Higher fee, but the actual fee per KB is much lower.
|
# Higher fee, but the actual fee per KB is much lower.
|
||||||
tx1b = CTransaction()
|
tx1b = CTransaction()
|
||||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||||
tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))]
|
tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000])), CTxOut(int(1.099*COIN))]
|
||||||
tx1b_hex = txToHex(tx1b)
|
tx1b_hex = txToHex(tx1b)
|
||||||
|
|
||||||
# Verify tx1b cannot replace tx1a.
|
# Verify tx1b cannot replace tx1a.
|
||||||
|
|
@ -559,14 +564,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
tx2a = CTransaction()
|
tx2a = CTransaction()
|
||||||
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||||
tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
tx2a.vout = [CTxOut(1*COIN, CScript([b'a'])), CTxOut(int(0.1*COIN))]
|
||||||
tx2a_hex = txToHex(tx2a)
|
tx2a_hex = txToHex(tx2a)
|
||||||
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
||||||
|
|
||||||
# Lower fee, but we'll prioritise it
|
# Lower fee, but we'll prioritise it
|
||||||
tx2b = CTransaction()
|
tx2b = CTransaction()
|
||||||
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||||
tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
|
tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a'])), CTxOut(int(0.09*COIN))]
|
||||||
tx2b.rehash()
|
tx2b.rehash()
|
||||||
tx2b_hex = txToHex(tx2b)
|
tx2b_hex = txToHex(tx2b)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue