text: #!/usr/bin/env python3
  # Copyright (c) 2015-2016 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 .script import (
      CScript,
      OP_CHECKSIG,
      OP_DUP,
      OP_EQUALVERIFY,
      OP_HASH160,
      OP_PUSHDATA2,
      OP_RETURN,
      OP_TRUE,
  )
  from .messages import (
      CBlock,
      COIN,
      COutPoint,
      CTransaction,
      CTxIn,
      CTxOut,
      FromHex,
      ToHex,
      ser_string,
  )
  from .txtools import pad_tx
  from .util import satoshi_round
  
  # 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
  
  
  def make_conform_to_ctor(block):
      for tx in block.vtx:
          pad_tx(tx)
          tx.rehash()
      block.vtx = [block.vtx[0]] + \
          sorted(block.vtx[1:], key=lambda tx: tx.get_id())
  
  
  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]
  
      # Make sure the coinbase is at least 100 bytes
      pad_tx(coinbase)
  
      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))
      pad_tx(tx)
      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
  
  
  def create_confirmed_utxos(node, count, age=101):
      """
      Helper to create at least "count" utxos
      """
      to_generate = int(0.5 * count) + age
      while to_generate > 0:
          node.generate(min(25, to_generate))
          to_generate -= 25
      utxos = node.listunspent()
      iterations = count - len(utxos)
      addr1 = node.getnewaddress()
      addr2 = node.getnewaddress()
      if iterations <= 0:
          return utxos
      for i in range(iterations):
          t = utxos.pop()
          inputs = []
          inputs.append({"txid": t["txid"], "vout": t["vout"]})
          outputs = {}
          outputs[addr1] = satoshi_round(t['amount'] / 2)
          outputs[addr2] = satoshi_round(t['amount'] / 2)
          raw_tx = node.createrawtransaction(inputs, outputs)
          ctx = FromHex(CTransaction(), raw_tx)
          fee = node.calculate_fee(ctx) // 2
          ctx.vout[0].nValue -= fee
          # Due to possible truncation, we go ahead and take another satoshi in
          # fees to ensure the transaction gets through
          ctx.vout[1].nValue -= fee + 1
          signed_tx = node.signrawtransaction(ToHex(ctx))["hex"]
          node.sendrawtransaction(signed_tx)
  
      while (node.getmempoolinfo()['size'] > 0):
          node.generate(1)
  
      utxos = node.listunspent()
      assert(len(utxos) >= count)
      return utxos
  
  
  def mine_big_block(node, utxos=None):
      # generate a 66k transaction,
      # and 14 of them is close to the 1MB block limit
      num = 14
      utxos = utxos if utxos is not None else []
      if len(utxos) < num:
          utxos.clear()
          utxos.extend(node.listunspent())
      send_big_transactions(node, utxos, num, 100)
      node.generate(1)
  
  
  def send_big_transactions(node, utxos, num, fee_multiplier):
      from .cashaddr import decode
      txids = []
      padding = "1"*(512*127)
      addrHash = decode(node.getnewaddress())[2]
  
      for _ in range(num):
          ctx = CTransaction()
          utxo = utxos.pop()
          txid = int(utxo['txid'], 16)
          ctx.vin.append(CTxIn(COutPoint(txid, int(utxo["vout"])), b""))
          ctx.vout.append(CTxOut(0, CScript(
              [OP_RETURN, OP_PUSHDATA2, len(padding), bytes(padding, 'utf-8')])))
          ctx.vout.append(
              CTxOut(int(satoshi_round(utxo['amount']*COIN)),
                     CScript([OP_DUP, OP_HASH160, addrHash, OP_EQUALVERIFY, OP_CHECKSIG])))
          # Create a proper fee for the transaction to be mined
          ctx.vout[1].nValue -= int(fee_multiplier * node.calculate_fee(ctx))
          signresult = node.signrawtransactionwithwallet(
              ToHex(ctx), None, "NONE|FORKID")
          txid = node.sendrawtransaction(signresult["hex"], True)
          txids.append(txid)
      return txids
  