Example #1
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 #2
0
  @Test
  public void testCreateMultiSigInputScript() throws AddressFormatException {
    // Setup transaction and signatures
    ECKey key1 =
        new DumpedPrivateKey(params, "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT")
            .getKey();
    ECKey key2 =
        new DumpedPrivateKey(params, "cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo")
            .getKey();
    ECKey key3 =
        new DumpedPrivateKey(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg")
            .getKey();
    Script multisigScript =
        ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
    byte[] bytes =
        Hex.decode(
            "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
    Transaction transaction = new Transaction(params, bytes);
    TransactionOutput output = transaction.getOutput(1);
    Transaction spendTx = new Transaction(params);
    Address address = new Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
    Script outputScript = ScriptBuilder.createOutputScript(address);
    spendTx.addOutput(output.getValue(), outputScript);
    spendTx.addInput(output);
    Sha256Hash sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false);
    ECKey.ECDSASignature party1Signature = key1.sign(sighash);
    ECKey.ECDSASignature party2Signature = key2.sign(sighash);
    TransactionSignature party1TransactionSignature =
        new TransactionSignature(party1Signature, SigHash.ALL, false);
    TransactionSignature party2TransactionSignature =
        new TransactionSignature(party2Signature, SigHash.ALL, false);

    // Create p2sh multisig input script
    Script inputScript =
        ScriptBuilder.createP2SHMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature),
            multisigScript.getProgram());

    // Assert that the input script contains 4 chunks
    assertTrue(inputScript.getChunks().size() == 4);

    // Assert that the input script created contains the original multisig
    // script as the last chunk
    ScriptChunk scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertArrayEquals(scriptChunk.data, multisigScript.getProgram());

    // Create regular multisig input script
    inputScript =
        ScriptBuilder.createMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature));

    // Assert that the input script only contains 3 chunks
    assertTrue(inputScript.getChunks().size() == 3);

    // Assert that the input script created does not end with the original
    // multisig script
    scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertThat(scriptChunk.data, IsNot.not(IsEqual.equalTo(multisigScript.getProgram())));
  }
Example #3
0
 /** Creates a fresh ScriptBuilder with the given program as the starting point. */
 public ScriptBuilder(Script template) {
   chunks = new ArrayList<ScriptChunk>(template.getChunks());
 }