basic implementation of transaction replacement. requires cleanup and testing
This commit is contained in:
@@ -4,6 +4,7 @@ import json
|
||||
import logging
|
||||
import binascii
|
||||
import struct
|
||||
import base64
|
||||
from testsupport import *
|
||||
|
||||
|
||||
@@ -91,20 +92,19 @@ def test_oversize_fulfillment(inp):
|
||||
|
||||
|
||||
@fanout_input(6)
|
||||
def test_aux_basic(inp):
|
||||
aux_cond = {
|
||||
'type': 'aux-sha-256',
|
||||
'method': 'equals',
|
||||
'conditionAux': 'LTE',
|
||||
'fulfillmentAux': 'LTE'
|
||||
def test_eval_basic(inp):
|
||||
eval_cond = {
|
||||
'type': 'eval-sha-256',
|
||||
'method': 'testEval',
|
||||
'params': encode_base64('testEval')
|
||||
}
|
||||
|
||||
# Setup some aux outputs
|
||||
# Setup some eval outputs
|
||||
spend0 = {
|
||||
'inputs': [inp],
|
||||
'outputs': [
|
||||
{'amount': 500, 'script': {'condition': aux_cond}},
|
||||
{'amount': 500, 'script': {'condition': aux_cond}}
|
||||
{'amount': 500, 'script': {'condition': eval_cond}},
|
||||
{'amount': 500, 'script': {'condition': eval_cond}}
|
||||
]
|
||||
}
|
||||
spend0_txid = submit(sign(spend0))
|
||||
@@ -112,17 +112,17 @@ def test_aux_basic(inp):
|
||||
|
||||
# Test a good fulfillment
|
||||
spend1 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': aux_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': aux_cond}}]
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': eval_cond}}]
|
||||
}
|
||||
spend1_txid = submit(sign(spend1))
|
||||
assert rpc.getrawtransaction(spend1_txid)
|
||||
|
||||
# Test a bad fulfillment
|
||||
aux_cond['fulfillmentAux'] = 'WYW'
|
||||
eval_cond['params'] = ''
|
||||
spend2 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': aux_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': aux_cond}}]
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': eval_cond}}],
|
||||
'outputs': [{'amount': 500, 'script': {'condition': eval_cond}}]
|
||||
}
|
||||
try:
|
||||
assert not submit(sign(spend2)), 'should raise an error'
|
||||
@@ -131,50 +131,6 @@ def test_aux_basic(inp):
|
||||
|
||||
|
||||
@fanout_input(7)
|
||||
def test_aux_complex(inp):
|
||||
aux_cond = {
|
||||
'type': 'aux-sha-256',
|
||||
'method': 'inputIsReturn',
|
||||
'conditionAux': '',
|
||||
'fulfillmentAux': 'AQ' # \1 (tx.vout[1])
|
||||
}
|
||||
|
||||
# Setup some aux outputs
|
||||
spend0 = {
|
||||
'inputs': [inp],
|
||||
'outputs': [
|
||||
{'amount': 500, 'script': {'condition': aux_cond}},
|
||||
{'amount': 500, 'script': {'condition': aux_cond}}
|
||||
]
|
||||
}
|
||||
spend0_txid = submit(sign(spend0))
|
||||
assert rpc.getrawtransaction(spend0_txid)
|
||||
|
||||
# Test a good fulfillment
|
||||
spend1 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': aux_cond}}],
|
||||
'outputs': [
|
||||
{'amount': 250, 'script': {'condition': aux_cond}},
|
||||
{'amount': 250, 'script': "6A0B68656C6C6F207468657265"} # OP_RETURN somedata
|
||||
]
|
||||
}
|
||||
spend1_txid = submit(sign(spend1))
|
||||
assert rpc.getrawtransaction(spend1_txid)
|
||||
|
||||
# Test a bad fulfillment
|
||||
spend2 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': aux_cond}}],
|
||||
'outputs': [
|
||||
{'amount': 500, 'script': "6A0B68656C6C6F207468657265"} # OP_RETURN somedata
|
||||
]
|
||||
}
|
||||
try:
|
||||
assert not submit(sign(spend2)), 'should raise an error'
|
||||
except RPCError as e:
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(8)
|
||||
def test_secp256k1_condition(inp):
|
||||
ec_cond = {
|
||||
'type': 'secp256k1-sha-256',
|
||||
@@ -214,6 +170,60 @@ def test_secp256k1_condition(inp):
|
||||
assert SCRIPT_FALSE in str(e), str(e)
|
||||
|
||||
|
||||
@fanout_input(20)
|
||||
def test_eval_replacement(inp):
|
||||
eval_cond = {
|
||||
'type': 'eval-sha-256',
|
||||
'method': 'testReplace',
|
||||
'params': '',
|
||||
}
|
||||
|
||||
# Setup replaceable output
|
||||
spend0 = {
|
||||
'inputs': [inp],
|
||||
'outputs': [
|
||||
{'amount': 1000, 'script': {'condition': eval_cond}},
|
||||
]
|
||||
}
|
||||
spend0_txid = submit(sign(spend0))
|
||||
assert rpc.getrawtransaction(spend0_txid)
|
||||
|
||||
b64_1 = 'AQ=='
|
||||
spend1 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}],
|
||||
'outputs': [{'amount': 1000, 'script': {'op_return': b64_1}}]
|
||||
}
|
||||
|
||||
b64_2 = 'Ag=='
|
||||
spend2 = {
|
||||
'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': eval_cond}}],
|
||||
'outputs': [{'amount': 1000, 'script': {'op_return': b64_2}}]
|
||||
}
|
||||
|
||||
# If spend2 is already registered, return true, as this test has already been performed
|
||||
spend2_txid = hoek.encodeTx(sign(spend2))['txid']
|
||||
try:
|
||||
rpc.getrawtransaction(spend2_txid)
|
||||
return
|
||||
except RPCError:
|
||||
pass
|
||||
|
||||
# Send replaceable
|
||||
spend1_txid = submit(sign(spend1))
|
||||
assert rpc.getrawtransaction(spend1_txid)
|
||||
|
||||
|
||||
# Send replacement (higher OP_RETURN data)
|
||||
spend2_txid = submit(sign(spend2))
|
||||
assert rpc.getrawtransaction(spend2_txid)
|
||||
|
||||
# Now the first transaction has gone
|
||||
try:
|
||||
assert not rpc.getrawtransaction(spend1_txid), "should raise an error"
|
||||
except RPCError as e:
|
||||
assert 'No information available about transaction' in str(e), str(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
for name, f in globals().items():
|
||||
|
||||
@@ -97,7 +97,7 @@ def get_fanout_txid():
|
||||
reward_tx = hoek.decodeTx({'hex': reward_tx_raw})
|
||||
balance = reward_tx['outputs'][0]['amount']
|
||||
|
||||
n_outs = 16
|
||||
n_outs = 40
|
||||
remainder = balance - n_outs * 1000
|
||||
|
||||
fanout = {
|
||||
@@ -109,7 +109,9 @@ def get_fanout_txid():
|
||||
] + [{"amount": remainder, 'script': {'address': notary_addr}}])
|
||||
}
|
||||
|
||||
return submit(sign(fanout))
|
||||
txid = submit(sign(fanout))
|
||||
rpc.getrawtransaction(txid)
|
||||
return txid
|
||||
|
||||
|
||||
def fanout_input(n):
|
||||
|
||||
Reference in New Issue
Block a user