/**
  * Create a program that satisfies a pay-to-script hashed OP_CHECKMULTISIG program. If given
  * signature list is null, incomplete scriptSig will be created with OP_0 instead of signatures
  */
 public static Script createP2SHMultiSigInputScript(
     @Nullable List<TransactionSignature> signatures, Script multisigProgram) {
   List<byte[]> sigs = new ArrayList<byte[]>();
   if (signatures == null) {
     // create correct number of empty signatures
     int numSigs = multisigProgram.getNumberOfSignaturesRequiredToSpend();
     for (int i = 0; i < numSigs; i++) sigs.add(new byte[] {});
   } else {
     for (TransactionSignature signature : signatures) {
       sigs.add(signature.encodeToBitcoin());
     }
   }
   return createMultiSigInputScriptBytes(sigs, multisigProgram.getProgram());
 }
  /**
   * Returns a copy of the given scriptSig with the signature inserted in the given position.
   *
   * <p>This function assumes that any missing sigs have OP_0 placeholders. If given scriptSig
   * already has all the signatures in place, IllegalArgumentException will be thrown.
   *
   * @param targetIndex where to insert the signature
   * @param sigsPrefixCount how many items to copy verbatim (e.g. initial OP_0 for multisig)
   * @param sigsSuffixCount how many items to copy verbatim at end (e.g. redeemScript for P2SH)
   */
  public static Script updateScriptWithSignature(
      Script scriptSig,
      byte[] signature,
      int targetIndex,
      int sigsPrefixCount,
      int sigsSuffixCount) {
    ScriptBuilder builder = new ScriptBuilder();
    List<ScriptChunk> inputChunks = scriptSig.getChunks();
    int totalChunks = inputChunks.size();

    // Check if we have a place to insert, otherwise just return given scriptSig unchanged.
    // We assume here that OP_0 placeholders always go after the sigs, so
    // to find if we have sigs missing, we can just check the chunk in latest sig position
    boolean hasMissingSigs = inputChunks.get(totalChunks - sigsSuffixCount - 1).equalsOpCode(OP_0);
    checkArgument(hasMissingSigs, "ScriptSig is already filled with signatures");

    // copy the prefix
    for (ScriptChunk chunk : inputChunks.subList(0, sigsPrefixCount)) builder.addChunk(chunk);

    // copy the sigs
    int pos = 0;
    boolean inserted = false;
    for (ScriptChunk chunk : inputChunks.subList(sigsPrefixCount, totalChunks - sigsSuffixCount)) {
      if (pos == targetIndex) {
        inserted = true;
        builder.data(signature);
        pos++;
      }
      if (!chunk.equalsOpCode(OP_0)) {
        builder.addChunk(chunk);
        pos++;
      }
    }

    // add OP_0's if needed, since we skipped them in the previous loop
    while (pos < totalChunks - sigsPrefixCount - sigsSuffixCount) {
      if (pos == targetIndex) {
        inserted = true;
        builder.data(signature);
      } else {
        builder.addChunk(new ScriptChunk(OP_0, null));
      }
      pos++;
    }

    // copy the suffix
    for (ScriptChunk chunk : inputChunks.subList(totalChunks - sigsSuffixCount, totalChunks))
      builder.addChunk(chunk);

    checkState(inserted);
    return builder.build();
  }
 /**
  * Adds a copy of the given byte array as a data element (i.e. PUSHDATA) at the given index in the
  * program.
  */
 public ScriptBuilder data(int index, byte[] data) {
   // implements BIP62
   byte[] copy = Arrays.copyOf(data, data.length);
   int opcode;
   if (data.length == 0) {
     opcode = OP_0;
   } else if (data.length == 1) {
     byte b = data[0];
     if (b >= 1 && b <= 16) opcode = Script.encodeToOpN(b);
     else opcode = 1;
   } else if (data.length < OP_PUSHDATA1) {
     opcode = data.length;
   } else if (data.length < 256) {
     opcode = OP_PUSHDATA1;
   } else if (data.length < 65536) {
     opcode = OP_PUSHDATA2;
   } else {
     throw new RuntimeException("Unimplemented");
   }
   return addChunk(index, new ScriptChunk(opcode, copy));
 }
 /** Creates a fresh ScriptBuilder with the given program as the starting point. */
 public ScriptBuilder(Script template) {
   chunks = new ArrayList<ScriptChunk>(template.getChunks());
 }
 /** Creates a scriptPubKey for the given redeem script. */
 public static Script createP2SHOutputScript(Script redeemScript) {
   byte[] hash = Utils.Hash160(redeemScript.getProgram());
   return ScriptBuilder.createP2SHOutputScript(hash);
 }
 /** Adds the given number as a OP_N opcode to the given index in the program. */
 public ScriptBuilder smallNum(int index, int num) {
   checkArgument(num >= 0, "Cannot encode negative numbers with smallNum");
   checkArgument(num <= 16, "Cannot encode numbers larger than 16 with smallNum");
   return addChunk(index, new ScriptChunk(Script.encodeToOpN(num), null));
 }