mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
4db16ec827
5fecd84
[tests] Remove redundant import in blocktools.py test (Anthony Towns)9b20bb4
[tests] Check tests conform to naming convention (Anthony Towns)7250b4e
[tests] README.md nit fixes (Anthony Towns)82b2712
[tests] move witness util functions to blocktools.py (John Newbery)1e10854
[tests] [docs] update README for new test naming scheme (John Newbery) Pull request description: Splitting #11774 into two parts -- this part updates the README with the proposed naming convention, and adds some checks to test_runner.py that the number of tests violating the naming convention doesn't increase too much. Idea is this part of the change should not introduce merge conflicts or require much rebasing, so reviews of the complicated bits won't become invalidated too often; while the second part will just be file renames, which will require regular rebasing and will introduce merge conflicts with pending PRs, but can be merged later, and should also be much easier to review, since it will only include relatively trivial changes. Tree-SHA512: b96557d41714addbbfe2aed62fb5a48639eaeb1eb3aba30ac1b3a86bb3cb8d796c6247f9c414c4695c4bf54c0ec9968ac88e2f88fb62483bc1a2f89368f7fc80
173 lines
6.3 KiB
Python
173 lines
6.3 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (c) 2015-2017 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
"""Utilities for manipulating blocks and transactions."""
|
|
|
|
from .address import (
|
|
key_to_p2sh_p2wpkh,
|
|
key_to_p2wpkh,
|
|
script_to_p2sh_p2wsh,
|
|
script_to_p2wsh,
|
|
)
|
|
from .mininode import *
|
|
from .script import (
|
|
CScript,
|
|
OP_0,
|
|
OP_1,
|
|
OP_CHECKMULTISIG,
|
|
OP_CHECKSIG,
|
|
OP_RETURN,
|
|
OP_TRUE,
|
|
hash160,
|
|
)
|
|
from .util import assert_equal
|
|
|
|
# Create a block (with regtest difficulty)
|
|
def create_block(hashprev, coinbase, nTime=None):
|
|
block = CBlock()
|
|
if nTime is None:
|
|
import time
|
|
block.nTime = int(time.time()+600)
|
|
else:
|
|
block.nTime = nTime
|
|
block.hashPrevBlock = hashprev
|
|
block.nBits = 0x207fffff # Will break after a difficulty adjustment...
|
|
block.vtx.append(coinbase)
|
|
block.hashMerkleRoot = block.calc_merkle_root()
|
|
block.calc_sha256()
|
|
return block
|
|
|
|
# From BIP141
|
|
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
|
|
|
|
|
|
def get_witness_script(witness_root, witness_nonce):
|
|
witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce)))
|
|
output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment)
|
|
return CScript([OP_RETURN, output_data])
|
|
|
|
|
|
# According to BIP141, blocks with witness rules active must commit to the
|
|
# hash of all in-block transactions including witness.
|
|
def add_witness_commitment(block, nonce=0):
|
|
# First calculate the merkle root of the block's
|
|
# transactions, with witnesses.
|
|
witness_nonce = nonce
|
|
witness_root = block.calc_witness_merkle_root()
|
|
# witness_nonce should go to coinbase witness.
|
|
block.vtx[0].wit.vtxinwit = [CTxInWitness()]
|
|
block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)]
|
|
|
|
# witness commitment is the last OP_RETURN output in coinbase
|
|
block.vtx[0].vout.append(CTxOut(0, get_witness_script(witness_root, witness_nonce)))
|
|
block.vtx[0].rehash()
|
|
block.hashMerkleRoot = block.calc_merkle_root()
|
|
block.rehash()
|
|
|
|
|
|
def serialize_script_num(value):
|
|
r = bytearray(0)
|
|
if value == 0:
|
|
return r
|
|
neg = value < 0
|
|
absvalue = -value if neg else value
|
|
while (absvalue):
|
|
r.append(int(absvalue & 0xff))
|
|
absvalue >>= 8
|
|
if r[-1] & 0x80:
|
|
r.append(0x80 if neg else 0)
|
|
elif neg:
|
|
r[-1] |= 0x80
|
|
return r
|
|
|
|
# Create a coinbase transaction, assuming no miner fees.
|
|
# If pubkey is passed in, the coinbase output will be a P2PK output;
|
|
# otherwise an anyone-can-spend output.
|
|
def create_coinbase(height, pubkey = None):
|
|
coinbase = CTransaction()
|
|
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
|
|
ser_string(serialize_script_num(height)), 0xffffffff))
|
|
coinbaseoutput = CTxOut()
|
|
coinbaseoutput.nValue = 50 * COIN
|
|
halvings = int(height/150) # regtest
|
|
coinbaseoutput.nValue >>= halvings
|
|
if (pubkey != None):
|
|
coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG])
|
|
else:
|
|
coinbaseoutput.scriptPubKey = CScript([OP_TRUE])
|
|
coinbase.vout = [ coinbaseoutput ]
|
|
coinbase.calc_sha256()
|
|
return coinbase
|
|
|
|
# Create a transaction.
|
|
# If the scriptPubKey is not specified, make it anyone-can-spend.
|
|
def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()):
|
|
tx = CTransaction()
|
|
assert(n < len(prevtx.vout))
|
|
tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff))
|
|
tx.vout.append(CTxOut(value, scriptPubKey))
|
|
tx.calc_sha256()
|
|
return tx
|
|
|
|
def get_legacy_sigopcount_block(block, fAccurate=True):
|
|
count = 0
|
|
for tx in block.vtx:
|
|
count += get_legacy_sigopcount_tx(tx, fAccurate)
|
|
return count
|
|
|
|
def get_legacy_sigopcount_tx(tx, fAccurate=True):
|
|
count = 0
|
|
for i in tx.vout:
|
|
count += i.scriptPubKey.GetSigOpCount(fAccurate)
|
|
for j in tx.vin:
|
|
# scriptSig might be of type bytes, so convert to CScript for the moment
|
|
count += CScript(j.scriptSig).GetSigOpCount(fAccurate)
|
|
return count
|
|
|
|
# Create a scriptPubKey corresponding to either a P2WPKH output for the
|
|
# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given
|
|
# pubkey. Returns the hex encoding of the scriptPubKey.
|
|
def witness_script(use_p2wsh, pubkey):
|
|
if (use_p2wsh == False):
|
|
# P2WPKH instead
|
|
pubkeyhash = hash160(hex_str_to_bytes(pubkey))
|
|
pkscript = CScript([OP_0, pubkeyhash])
|
|
else:
|
|
# 1-of-1 multisig
|
|
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)
|
|
|
|
# Return a transaction (in hex) that spends the given utxo to a segwit output,
|
|
# optionally wrapping the segwit output using P2SH.
|
|
def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
|
|
if use_p2wsh:
|
|
program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
|
|
addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program)
|
|
else:
|
|
addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
|
|
if not encode_p2sh:
|
|
assert_equal(node.validateaddress(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey))
|
|
return node.createrawtransaction([utxo], {addr: amount})
|
|
|
|
# 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;
|
|
# 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_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount)
|
|
if (sign):
|
|
signed = node.signrawtransaction(tx_to_witness)
|
|
assert("errors" not in signed or len(["errors"]) == 0)
|
|
return node.sendrawtransaction(signed["hex"])
|
|
else:
|
|
if (insert_redeem_script):
|
|
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)
|