Example #1
0
 /**
  * Create a program that satisfies an OP_CHECKMULTISIG program, using pre-encoded signatures.
  * Optionally, appends the script program bytes if spending a P2SH output.
  */
 public static Script createMultiSigInputScriptBytes(
     List<byte[]> signatures, @Nullable byte[] multisigProgramBytes) {
   checkArgument(signatures.size() <= 16);
   ScriptBuilder builder = new ScriptBuilder();
   builder.smallNum(
       0); // Work around a bug in CHECKMULTISIG that is now a required part of the protocol.
   for (byte[] signature : signatures) builder.data(signature);
   if (multisigProgramBytes != null) builder.data(multisigProgramBytes);
   return builder.build();
 }
Example #2
0
  /**
   * 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();
  }
Example #3
0
 /**
  * Creates a program that requires at least N of the given keys to sign, using OP_CHECKMULTISIG.
  */
 public static Script createMultiSigOutputScript(int threshold, List<ECKey> pubkeys) {
   checkArgument(threshold > 0);
   checkArgument(threshold <= pubkeys.size());
   checkArgument(pubkeys.size() <= 16); // That's the max we can represent with a single opcode.
   ScriptBuilder builder = new ScriptBuilder();
   builder.smallNum(threshold);
   for (ECKey key : pubkeys) {
     builder.data(key.getPubKey());
   }
   builder.smallNum(pubkeys.size());
   builder.op(OP_CHECKMULTISIG);
   return builder.build();
 }
Example #4
0
 /**
  * Creates redeem script with given public keys and threshold. Given public keys will be placed in
  * redeem script in the lexicographical sorting order.
  */
 public static Script createRedeemScript(int threshold, List<ECKey> pubkeys) {
   pubkeys = new ArrayList<ECKey>(pubkeys);
   Collections.sort(pubkeys, ECKey.PUBKEY_COMPARATOR);
   return ScriptBuilder.createMultiSigOutputScript(threshold, pubkeys);
 }
Example #5
0
 /** Creates a scriptPubKey for the given redeem script. */
 public static Script createP2SHOutputScript(Script redeemScript) {
   byte[] hash = Utils.Hash160(redeemScript.getProgram());
   return ScriptBuilder.createP2SHOutputScript(hash);
 }