mirror of
https://github.com/dashpay/dash.git
synced 2024-12-27 04:52:59 +01:00
Use BIP173 addresses in segwit.py test
This commit is contained in:
parent
e278f12ca7
commit
fd0041aa27
@ -7,7 +7,7 @@
|
|||||||
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, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex
|
from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex
|
||||||
from test_framework.address import script_to_p2sh, key_to_p2pkh
|
from test_framework.address import script_to_p2sh, key_to_p2pkh, key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2sh_p2wsh, script_to_p2wsh, program_to_witness
|
||||||
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, OP_TRUE
|
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, OP_TRUE
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
@ -33,15 +33,15 @@ def witness_script(use_p2wsh, pubkey):
|
|||||||
|
|
||||||
# Return a transaction (in hex) that spends the given utxo to a segwit output,
|
# Return a transaction (in hex) that spends the given utxo to a segwit output,
|
||||||
# optionally wrapping the segwit output using P2SH.
|
# optionally wrapping the segwit output using P2SH.
|
||||||
def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
|
def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
|
||||||
pkscript = hex_str_to_bytes(witness_script(use_p2wsh, pubkey))
|
if use_p2wsh:
|
||||||
if (encode_p2sh):
|
program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
|
||||||
p2sh_hash = hash160(pkscript)
|
addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program)
|
||||||
pkscript = CScript([OP_HASH160, p2sh_hash, OP_EQUAL])
|
else:
|
||||||
tx = CTransaction()
|
addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
|
||||||
tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), b""))
|
if not encode_p2sh:
|
||||||
tx.vout.append(CTxOut(int(amount*COIN), pkscript))
|
assert_equal(node.validateaddress(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey))
|
||||||
return ToHex(tx)
|
return node.createrawtransaction([utxo], {addr: amount})
|
||||||
|
|
||||||
# Create a transaction spending a given utxo to a segwit output corresponding
|
# Create a transaction spending a given utxo to a segwit output corresponding
|
||||||
# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
|
# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
|
||||||
@ -49,7 +49,7 @@ def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
|
|||||||
# sign=True will have the given node sign the transaction.
|
# sign=True will have the given node sign the transaction.
|
||||||
# insert_redeem_script will be added to the scriptSig, if given.
|
# 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=""):
|
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)
|
tx_to_witness = create_witness_tx(node, 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)
|
||||||
@ -133,8 +133,15 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
newaddress = self.nodes[i].getnewaddress()
|
newaddress = self.nodes[i].getnewaddress()
|
||||||
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
|
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
|
||||||
multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
|
multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
|
||||||
self.nodes[i].addwitnessaddress(newaddress)
|
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
|
||||||
self.nodes[i].addwitnessaddress(multiaddress)
|
p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True)
|
||||||
|
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
|
||||||
|
p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, True)
|
||||||
|
bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False)
|
||||||
|
assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1]))
|
||||||
|
assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1]))
|
||||||
|
assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))
|
||||||
|
assert_equal(bip173_ms_addr, script_to_p2wsh(multiscript))
|
||||||
p2sh_ids.append([])
|
p2sh_ids.append([])
|
||||||
wit_ids.append([])
|
wit_ids.append([])
|
||||||
for v in range(2):
|
for v in range(2):
|
||||||
@ -558,6 +565,13 @@ class SegWitTest(BitcoinTestFramework):
|
|||||||
solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1))
|
solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1))
|
||||||
self.mine_and_test_listunspent(unseen_anytime, 0)
|
self.mine_and_test_listunspent(unseen_anytime, 0)
|
||||||
|
|
||||||
|
# Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works
|
||||||
|
v1_addr = program_to_witness(1, [3,5])
|
||||||
|
v1_tx = self.nodes[0].createrawtransaction([getutxo(spendable_txid[0])],{v1_addr: 1})
|
||||||
|
v1_decoded = self.nodes[1].decoderawtransaction(v1_tx)
|
||||||
|
assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr)
|
||||||
|
assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305")
|
||||||
|
|
||||||
# Check that spendable outputs are really spendable
|
# Check that spendable outputs are really spendable
|
||||||
self.create_and_mine_tx_from_txids(spendable_txid)
|
self.create_and_mine_tx_from_txids(spendable_txid)
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
from .script import hash256, hash160, sha256, CScript, OP_0
|
from .script import hash256, hash160, sha256, CScript, OP_0
|
||||||
from .util import bytes_to_hex_str, hex_str_to_bytes
|
from .util import bytes_to_hex_str, hex_str_to_bytes
|
||||||
|
|
||||||
|
from . import segwit_addr
|
||||||
|
|
||||||
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||||
|
|
||||||
def byte_to_base58(b, version):
|
def byte_to_base58(b, version):
|
||||||
@ -44,6 +46,32 @@ def script_to_p2sh(script, main = False):
|
|||||||
script = check_script(script)
|
script = check_script(script)
|
||||||
return scripthash_to_p2sh(hash160(script), main)
|
return scripthash_to_p2sh(hash160(script), main)
|
||||||
|
|
||||||
|
def key_to_p2sh_p2wpkh(key, main = False):
|
||||||
|
key = check_key(key)
|
||||||
|
p2shscript = CScript([OP_0, hash160(key)])
|
||||||
|
return script_to_p2sh(p2shscript, main)
|
||||||
|
|
||||||
|
def program_to_witness(version, program, main = False):
|
||||||
|
if (type(program) is str):
|
||||||
|
program = hex_str_to_bytes(program)
|
||||||
|
assert 0 <= version <= 16
|
||||||
|
assert 2 <= len(program) <= 40
|
||||||
|
assert version > 0 or len(program) in [20, 32]
|
||||||
|
return segwit_addr.encode("bc" if main else "bcrt", version, program)
|
||||||
|
|
||||||
|
def script_to_p2wsh(script, main = False):
|
||||||
|
script = check_script(script)
|
||||||
|
return program_to_witness(0, sha256(script), main)
|
||||||
|
|
||||||
|
def key_to_p2wpkh(key, main = False):
|
||||||
|
key = check_key(key)
|
||||||
|
return program_to_witness(0, hash160(key), main)
|
||||||
|
|
||||||
|
def script_to_p2sh_p2wsh(script, main = False):
|
||||||
|
script = check_script(script)
|
||||||
|
p2shscript = CScript([OP_0, sha256(script)])
|
||||||
|
return script_to_p2sh(p2shscript, main)
|
||||||
|
|
||||||
def check_key(key):
|
def check_key(key):
|
||||||
if (type(key) is str):
|
if (type(key) is str):
|
||||||
key = hex_str_to_bytes(key) # Assuming this is hex string
|
key = hex_str_to_bytes(key) # Assuming this is hex string
|
||||||
|
107
test/functional/test_framework/segwit_addr.py
Normal file
107
test/functional/test_framework/segwit_addr.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (c) 2017 Pieter Wuille
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
"""Reference implementation for Bech32 and segwit addresses."""
|
||||||
|
|
||||||
|
|
||||||
|
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_polymod(values):
|
||||||
|
"""Internal function that computes the Bech32 checksum."""
|
||||||
|
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
|
||||||
|
chk = 1
|
||||||
|
for value in values:
|
||||||
|
top = chk >> 25
|
||||||
|
chk = (chk & 0x1ffffff) << 5 ^ value
|
||||||
|
for i in range(5):
|
||||||
|
chk ^= generator[i] if ((top >> i) & 1) else 0
|
||||||
|
return chk
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_hrp_expand(hrp):
|
||||||
|
"""Expand the HRP into values for checksum computation."""
|
||||||
|
return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_verify_checksum(hrp, data):
|
||||||
|
"""Verify a checksum given HRP and converted data characters."""
|
||||||
|
return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_create_checksum(hrp, data):
|
||||||
|
"""Compute the checksum values given HRP and data."""
|
||||||
|
values = bech32_hrp_expand(hrp) + data
|
||||||
|
polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
|
||||||
|
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_encode(hrp, data):
|
||||||
|
"""Compute a Bech32 string given HRP and data values."""
|
||||||
|
combined = data + bech32_create_checksum(hrp, data)
|
||||||
|
return hrp + '1' + ''.join([CHARSET[d] for d in combined])
|
||||||
|
|
||||||
|
|
||||||
|
def bech32_decode(bech):
|
||||||
|
"""Validate a Bech32 string, and determine HRP and data."""
|
||||||
|
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
|
||||||
|
(bech.lower() != bech and bech.upper() != bech)):
|
||||||
|
return (None, None)
|
||||||
|
bech = bech.lower()
|
||||||
|
pos = bech.rfind('1')
|
||||||
|
if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
|
||||||
|
return (None, None)
|
||||||
|
if not all(x in CHARSET for x in bech[pos+1:]):
|
||||||
|
return (None, None)
|
||||||
|
hrp = bech[:pos]
|
||||||
|
data = [CHARSET.find(x) for x in bech[pos+1:]]
|
||||||
|
if not bech32_verify_checksum(hrp, data):
|
||||||
|
return (None, None)
|
||||||
|
return (hrp, data[:-6])
|
||||||
|
|
||||||
|
|
||||||
|
def convertbits(data, frombits, tobits, pad=True):
|
||||||
|
"""General power-of-2 base conversion."""
|
||||||
|
acc = 0
|
||||||
|
bits = 0
|
||||||
|
ret = []
|
||||||
|
maxv = (1 << tobits) - 1
|
||||||
|
max_acc = (1 << (frombits + tobits - 1)) - 1
|
||||||
|
for value in data:
|
||||||
|
if value < 0 or (value >> frombits):
|
||||||
|
return None
|
||||||
|
acc = ((acc << frombits) | value) & max_acc
|
||||||
|
bits += frombits
|
||||||
|
while bits >= tobits:
|
||||||
|
bits -= tobits
|
||||||
|
ret.append((acc >> bits) & maxv)
|
||||||
|
if pad:
|
||||||
|
if bits:
|
||||||
|
ret.append((acc << (tobits - bits)) & maxv)
|
||||||
|
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
|
||||||
|
return None
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def decode(hrp, addr):
|
||||||
|
"""Decode a segwit address."""
|
||||||
|
hrpgot, data = bech32_decode(addr)
|
||||||
|
if hrpgot != hrp:
|
||||||
|
return (None, None)
|
||||||
|
decoded = convertbits(data[1:], 5, 8, False)
|
||||||
|
if decoded is None or len(decoded) < 2 or len(decoded) > 40:
|
||||||
|
return (None, None)
|
||||||
|
if data[0] > 16:
|
||||||
|
return (None, None)
|
||||||
|
if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
|
||||||
|
return (None, None)
|
||||||
|
return (data[0], decoded)
|
||||||
|
|
||||||
|
|
||||||
|
def encode(hrp, witver, witprog):
|
||||||
|
"""Encode a segwit address."""
|
||||||
|
ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
|
||||||
|
if decode(hrp, ret) == (None, None):
|
||||||
|
return None
|
||||||
|
return ret
|
Loading…
Reference in New Issue
Block a user