mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-13 00:28:03 +00:00
Merge #9970: Improve readability of segwit.py, smartfees.py
1269b8a
Fix logging bug and improve readability of smartfees.py (Suhas Daftuar)b9f34e8
Improve readability of segwit.py (Suhas Daftuar) Tree-SHA512: 2c8ff61678c6c407a95a6530e9bd650ae6bb7c9e52f6dd5f256e19253a1358dd1a7aa33a9639fcb07f443e3a21dae71b9f0865c5f1fcaacb2097a3c6766c7eef
This commit is contained in:
commit
3cc13eac40
@ -102,7 +102,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
|
|||||||
segwit_out = rbf_node.validateaddress(rbf_node.getnewaddress())
|
segwit_out = rbf_node.validateaddress(rbf_node.getnewaddress())
|
||||||
rbf_node.addwitnessaddress(segwit_out["address"])
|
rbf_node.addwitnessaddress(segwit_out["address"])
|
||||||
segwitid = send_to_witness(
|
segwitid = send_to_witness(
|
||||||
version=0,
|
use_p2wsh=False,
|
||||||
node=rbf_node,
|
node=rbf_node,
|
||||||
utxo=segwit_in,
|
utxo=segwit_in,
|
||||||
pubkey=segwit_out["pubkey"],
|
pubkey=segwit_out["pubkey"],
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import *
|
||||||
from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut
|
from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut, COIN
|
||||||
from test_framework.address import script_to_p2sh, key_to_p2pkh
|
from test_framework.address import script_to_p2sh, key_to_p2pkh
|
||||||
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG
|
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, hash160
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from test_framework.mininode import FromHex
|
from test_framework.mininode import FromHex, ToHex
|
||||||
|
|
||||||
NODE_0 = 0
|
NODE_0 = 0
|
||||||
NODE_1 = 1
|
NODE_1 = 1
|
||||||
@ -18,47 +18,49 @@ NODE_2 = 2
|
|||||||
WIT_V0 = 0
|
WIT_V0 = 0
|
||||||
WIT_V1 = 1
|
WIT_V1 = 1
|
||||||
|
|
||||||
def witness_script(version, pubkey):
|
# Create a scriptPubKey corresponding to either a P2WPKH output for the
|
||||||
if (version == 0):
|
# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given
|
||||||
pubkeyhash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pubkey))))
|
# pubkey. Returns the hex encoding of the scriptPubKey.
|
||||||
pkscript = "0014" + pubkeyhash
|
def witness_script(use_p2wsh, pubkey):
|
||||||
elif (version == 1):
|
if (use_p2wsh == False):
|
||||||
# 1-of-1 multisig
|
# P2WPKH instead
|
||||||
scripthash = bytes_to_hex_str(sha256(hex_str_to_bytes("5121" + pubkey + "51ae")))
|
pubkeyhash = hash160(hex_str_to_bytes(pubkey))
|
||||||
pkscript = "0020" + scripthash
|
pkscript = CScript([OP_0, pubkeyhash])
|
||||||
else:
|
else:
|
||||||
assert("Wrong version" == "0 or 1")
|
# 1-of-1 multisig
|
||||||
return pkscript
|
witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
|
||||||
|
scripthash = sha256(witness_program)
|
||||||
|
pkscript = CScript([OP_0, scripthash])
|
||||||
|
return bytes_to_hex_str(pkscript)
|
||||||
|
|
||||||
def addlength(script):
|
# Return a transaction (in hex) that spends the given utxo to a segwit output,
|
||||||
scriptlen = format(len(script)//2, 'x')
|
# optionally wrapping the segwit output using P2SH.
|
||||||
assert(len(scriptlen) == 2)
|
def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
|
||||||
return scriptlen + script
|
pkscript = hex_str_to_bytes(witness_script(use_p2wsh, pubkey))
|
||||||
|
|
||||||
def create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount):
|
|
||||||
pkscript = witness_script(version, pubkey)
|
|
||||||
if (encode_p2sh):
|
if (encode_p2sh):
|
||||||
p2sh_hash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pkscript))))
|
p2sh_hash = hash160(pkscript)
|
||||||
pkscript = "a914"+p2sh_hash+"87"
|
pkscript = CScript([OP_HASH160, p2sh_hash, OP_EQUAL])
|
||||||
inputs = []
|
tx = CTransaction()
|
||||||
outputs = {}
|
tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), b""))
|
||||||
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]} )
|
tx.vout.append(CTxOut(int(amount*COIN), pkscript))
|
||||||
DUMMY_P2SH = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP"
|
return ToHex(tx)
|
||||||
outputs[DUMMY_P2SH] = amount
|
|
||||||
tx_to_witness = node.createrawtransaction(inputs,outputs)
|
|
||||||
#replace dummy output with our own
|
|
||||||
tx_to_witness = tx_to_witness[0:110] + addlength(pkscript) + tx_to_witness[-8:]
|
|
||||||
return tx_to_witness
|
|
||||||
|
|
||||||
def send_to_witness(version, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
|
# Create a transaction spending a given utxo to a segwit output corresponding
|
||||||
tx_to_witness = create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount)
|
# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
|
||||||
|
# encode_p2sh determines whether to wrap in P2SH.
|
||||||
|
# sign=True will have the given node sign the transaction.
|
||||||
|
# insert_redeem_script will be added to the scriptSig, if given.
|
||||||
|
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
|
||||||
|
tx_to_witness = create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount)
|
||||||
if (sign):
|
if (sign):
|
||||||
signed = node.signrawtransaction(tx_to_witness)
|
signed = node.signrawtransaction(tx_to_witness)
|
||||||
assert("errors" not in signed or len(["errors"]) == 0)
|
assert("errors" not in signed or len(["errors"]) == 0)
|
||||||
return node.sendrawtransaction(signed["hex"])
|
return node.sendrawtransaction(signed["hex"])
|
||||||
else:
|
else:
|
||||||
if (insert_redeem_script):
|
if (insert_redeem_script):
|
||||||
tx_to_witness = tx_to_witness[0:82] + addlength(insert_redeem_script) + tx_to_witness[84:]
|
tx = FromHex(CTransaction(), tx_to_witness)
|
||||||
|
tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)])
|
||||||
|
tx_to_witness = ToHex(tx)
|
||||||
|
|
||||||
return node.sendrawtransaction(tx_to_witness)
|
return node.sendrawtransaction(tx_to_witness)
|
||||||
|
|
||||||
@ -180,8 +182,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False)
|
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False)
|
||||||
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False)
|
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False)
|
||||||
# unsigned with redeem script
|
# unsigned with redeem script
|
||||||
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, addlength(witness_script(0, self.pubkey[0])))
|
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0]))
|
||||||
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, addlength(witness_script(1, self.pubkey[0])))
|
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0]))
|
||||||
# signed
|
# signed
|
||||||
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True)
|
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True)
|
||||||
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True)
|
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True)
|
||||||
@ -205,8 +207,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False)
|
self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False)
|
||||||
|
|
||||||
self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork")
|
self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork")
|
||||||
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, addlength(witness_script(0, self.pubkey[2]))) #block 430
|
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430
|
||||||
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, addlength(witness_script(1, self.pubkey[2]))) #block 431
|
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431
|
||||||
|
|
||||||
self.log.info("Verify previous witness txs skipped for mining can now be mined")
|
self.log.info("Verify previous witness txs skipped for mining can now be mined")
|
||||||
assert_equal(len(self.nodes[2].getrawmempool()), 4)
|
assert_equal(len(self.nodes[2].getrawmempool()), 4)
|
||||||
@ -230,8 +232,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
self.log.info("Verify witness txs without witness data are invalid after the fork")
|
self.log.info("Verify witness txs without witness data are invalid after the fork")
|
||||||
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
|
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
|
||||||
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False)
|
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False)
|
||||||
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, addlength(witness_script(0, self.pubkey[2])))
|
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, witness_script(False, self.pubkey[2]))
|
||||||
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, addlength(witness_script(1, self.pubkey[2])))
|
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, witness_script(True, self.pubkey[2]))
|
||||||
|
|
||||||
self.log.info("Verify default node can now use witness txs")
|
self.log.info("Verify default node can now use witness txs")
|
||||||
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432
|
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432
|
||||||
|
@ -7,15 +7,19 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import *
|
from test_framework.util import *
|
||||||
|
from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE
|
||||||
|
from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, FromHex, COIN
|
||||||
|
|
||||||
# Construct 2 trivial P2SH's and the ScriptSigs that spend them
|
# Construct 2 trivial P2SH's and the ScriptSigs that spend them
|
||||||
# So we can create many many transactions without needing to spend
|
# So we can create many many transactions without needing to spend
|
||||||
# time signing.
|
# time signing.
|
||||||
P2SH_1 = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP"
|
redeem_script_1 = CScript([OP_1, OP_DROP])
|
||||||
P2SH_2 = "2NBdpwq8Aoo1EEKEXPNrKvr5xQr3M9UfcZA" # P2SH of "OP_2 OP_DROP"
|
redeem_script_2 = CScript([OP_2, OP_DROP])
|
||||||
|
P2SH_1 = CScript([OP_HASH160, hash160(redeem_script_1), OP_EQUAL])
|
||||||
|
P2SH_2 = CScript([OP_HASH160, hash160(redeem_script_2), OP_EQUAL])
|
||||||
|
|
||||||
# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
|
# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
|
||||||
# 4 bytes of OP_TRUE and push 2-byte redeem script of "OP_1 OP_DROP" or "OP_2 OP_DROP"
|
SCRIPT_SIG = [CScript([OP_TRUE, redeem_script_1]), CScript([OP_TRUE, redeem_script_2])]
|
||||||
SCRIPT_SIG = ["0451025175", "0451025275"]
|
|
||||||
|
|
||||||
global log
|
global log
|
||||||
|
|
||||||
@ -35,39 +39,30 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee
|
|||||||
rand_fee = float(fee_increment)*(1.1892**random.randint(0,28))
|
rand_fee = float(fee_increment)*(1.1892**random.randint(0,28))
|
||||||
# Total fee ranges from min_fee to min_fee + 127*fee_increment
|
# Total fee ranges from min_fee to min_fee + 127*fee_increment
|
||||||
fee = min_fee - fee_increment + satoshi_round(rand_fee)
|
fee = min_fee - fee_increment + satoshi_round(rand_fee)
|
||||||
inputs = []
|
tx = CTransaction()
|
||||||
total_in = Decimal("0.00000000")
|
total_in = Decimal("0.00000000")
|
||||||
while total_in <= (amount + fee) and len(conflist) > 0:
|
while total_in <= (amount + fee) and len(conflist) > 0:
|
||||||
t = conflist.pop(0)
|
t = conflist.pop(0)
|
||||||
total_in += t["amount"]
|
total_in += t["amount"]
|
||||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]} )
|
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), b""))
|
||||||
if total_in <= amount + fee:
|
if total_in <= amount + fee:
|
||||||
while total_in <= (amount + fee) and len(unconflist) > 0:
|
while total_in <= (amount + fee) and len(unconflist) > 0:
|
||||||
t = unconflist.pop(0)
|
t = unconflist.pop(0)
|
||||||
total_in += t["amount"]
|
total_in += t["amount"]
|
||||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]} )
|
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), b""))
|
||||||
if total_in <= amount + fee:
|
if total_in <= amount + fee:
|
||||||
raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in))
|
raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in))
|
||||||
outputs = {}
|
tx.vout.append(CTxOut(int((total_in - amount - fee)*COIN), P2SH_1))
|
||||||
outputs = OrderedDict([(P2SH_1, total_in - amount - fee),
|
tx.vout.append(CTxOut(int(amount*COIN), P2SH_2))
|
||||||
(P2SH_2, amount)])
|
# These transactions don't need to be signed, but we still have to insert
|
||||||
rawtx = from_node.createrawtransaction(inputs, outputs)
|
# the ScriptSig that will satisfy the ScriptPubKey.
|
||||||
# createrawtransaction constructs a transaction that is ready to be signed.
|
for inp in tx.vin:
|
||||||
# These transactions don't need to be signed, but we still have to insert the ScriptSig
|
inp.scriptSig = SCRIPT_SIG[inp.prevout.n]
|
||||||
# that will satisfy the ScriptPubKey.
|
txid = from_node.sendrawtransaction(ToHex(tx), True)
|
||||||
completetx = rawtx[0:10]
|
|
||||||
inputnum = 0
|
|
||||||
for inp in inputs:
|
|
||||||
completetx += rawtx[10+82*inputnum:82+82*inputnum]
|
|
||||||
completetx += SCRIPT_SIG[inp["vout"]]
|
|
||||||
completetx += rawtx[84+82*inputnum:92+82*inputnum]
|
|
||||||
inputnum += 1
|
|
||||||
completetx += rawtx[10+82*inputnum:]
|
|
||||||
txid = from_node.sendrawtransaction(completetx, True)
|
|
||||||
unconflist.append({ "txid" : txid, "vout" : 0 , "amount" : total_in - amount - fee})
|
unconflist.append({ "txid" : txid, "vout" : 0 , "amount" : total_in - amount - fee})
|
||||||
unconflist.append({ "txid" : txid, "vout" : 1 , "amount" : amount})
|
unconflist.append({ "txid" : txid, "vout" : 1 , "amount" : amount})
|
||||||
|
|
||||||
return (completetx, fee)
|
return (ToHex(tx), fee)
|
||||||
|
|
||||||
def split_inputs(from_node, txins, txouts, initial_split = False):
|
def split_inputs(from_node, txins, txouts, initial_split = False):
|
||||||
"""
|
"""
|
||||||
@ -78,18 +73,21 @@ def split_inputs(from_node, txins, txouts, initial_split = False):
|
|||||||
a high coin age when the notion of priority still existed.
|
a high coin age when the notion of priority still existed.
|
||||||
"""
|
"""
|
||||||
prevtxout = txins.pop()
|
prevtxout = txins.pop()
|
||||||
inputs = []
|
tx = CTransaction()
|
||||||
inputs.append({ "txid" : prevtxout["txid"], "vout" : prevtxout["vout"] })
|
tx.vin.append(CTxIn(COutPoint(int(prevtxout["txid"], 16), prevtxout["vout"]), b""))
|
||||||
|
|
||||||
half_change = satoshi_round(prevtxout["amount"]/2)
|
half_change = satoshi_round(prevtxout["amount"]/2)
|
||||||
rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000")
|
rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000")
|
||||||
outputs = OrderedDict([(P2SH_1, half_change), (P2SH_2, rem_change)])
|
tx.vout.append(CTxOut(int(half_change*COIN), P2SH_1))
|
||||||
rawtx = from_node.createrawtransaction(inputs, outputs)
|
tx.vout.append(CTxOut(int(rem_change*COIN), P2SH_2))
|
||||||
|
|
||||||
# If this is the initial split we actually need to sign the transaction
|
# If this is the initial split we actually need to sign the transaction
|
||||||
# Otherwise we just need to insert the property ScriptSig
|
# Otherwise we just need to insert the proper ScriptSig
|
||||||
if (initial_split) :
|
if (initial_split) :
|
||||||
completetx = from_node.signrawtransaction(rawtx)["hex"]
|
completetx = from_node.signrawtransaction(ToHex(tx))["hex"]
|
||||||
else :
|
else :
|
||||||
completetx = rawtx[0:82] + SCRIPT_SIG[prevtxout["vout"]] + rawtx[84:]
|
tx.vin[0].scriptSig = SCRIPT_SIG[prevtxout["vout"]]
|
||||||
|
completetx = ToHex(tx)
|
||||||
txid = from_node.sendrawtransaction(completetx, True)
|
txid = from_node.sendrawtransaction(completetx, True)
|
||||||
txouts.append({ "txid" : txid, "vout" : 0 , "amount" : half_change})
|
txouts.append({ "txid" : txid, "vout" : 0 , "amount" : half_change})
|
||||||
txouts.append({ "txid" : txid, "vout" : 1 , "amount" : rem_change})
|
txouts.append({ "txid" : txid, "vout" : 1 , "amount" : rem_change})
|
||||||
|
Loading…
Reference in New Issue
Block a user