예제 #1
0
  /** Create a program that satisfies an OP_CHECKMULTISIG program. */
  public static Script createMultiSigInputScript(List<TransactionSignature> signatures) {
    List<byte[]> sigs = new ArrayList<byte[]>(signatures.size());
    for (TransactionSignature signature : signatures) {
      sigs.add(signature.encodeToPeercoin());
    }

    return createMultiSigInputScriptBytes(sigs, null);
  }
예제 #2
0
 /**
  * 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.encodeToPeercoin());
     }
   }
   return createMultiSigInputScriptBytes(sigs, multisigProgram.getProgram());
 }
  @Override
  public boolean signInputs(ProposedTransaction propTx, KeyBag keyBag) {
    Transaction tx = propTx.partialTx;
    int numInputs = tx.getInputs().size();
    for (int i = 0; i < numInputs; i++) {
      TransactionInput txIn = tx.getInput(i);
      if (txIn.getConnectedOutput() == null) {
        log.warn("Missing connected output, assuming input {} is already signed.", i);
        continue;
      }

      try {
        // We assume if its already signed, its hopefully got a SIGHASH type that will not
        // invalidate when
        // we sign missing pieces (to check this would require either assuming any signatures are
        // signing
        // standard output types or a way to get processed signatures out of script execution)
        txIn.getScriptSig().correctlySpends(tx, i, txIn.getConnectedOutput().getScriptPubKey());
        log.warn(
            "Input {} already correctly spends output, assuming SIGHASH type used will be safe and skipping signing.",
            i);
        continue;
      } catch (ScriptException e) {
        // Expected.
      }

      RedeemData redeemData = txIn.getConnectedRedeemData(keyBag);

      Script scriptPubKey = txIn.getConnectedOutput().getScriptPubKey();

      // For P2SH inputs we need to share derivation path of the signing key with other signers, so
      // that they
      // use correct key to calculate their signatures.
      // Married keys all have the same derivation path, so we can safely just take first one here.
      ECKey pubKey = redeemData.keys.get(0);
      if (pubKey instanceof DeterministicKey)
        propTx.keyPaths.put(scriptPubKey, (((DeterministicKey) pubKey).getPath()));

      ECKey key;
      // locate private key in redeem data. For pay-to-address and pay-to-key inputs RedeemData will
      // always contain
      // only one key (with private bytes). For P2SH inputs RedeemData will contain multiple keys,
      // one of which MAY
      // have private bytes
      if (redeemData == null || (key = redeemData.getFullKey()) == null) {
        log.warn("No local key found for input {}", i);
        continue;
      }

      Script inputScript = txIn.getScriptSig();
      // script here would be either a standard CHECKSIG program for pay-to-address or pay-to-pubkey
      // inputs or
      // a CHECKMULTISIG program for P2SH inputs
      byte[] script = redeemData.redeemScript.getProgram();
      try {
        TransactionSignature signature =
            tx.calculateSignature(i, key, script, Transaction.SigHash.ALL, false);

        // at this point we have incomplete inputScript with OP_0 in place of one or more
        // signatures. We already
        // have calculated the signature using the local key and now need to insert it in the
        // correct place
        // within inputScript. For pay-to-address and pay-to-key script there is only one signature
        // and it always
        // goes first in an inputScript (sigIndex = 0). In P2SH input scripts we need to figure out
        // our relative
        // position relative to other signers.  Since we don't have that information at this point,
        // and since
        // we always run first, we have to depend on the other signers rearranging the signatures as
        // needed.
        // Therefore, always place as first signature.
        int sigIndex = 0;
        inputScript =
            scriptPubKey.getScriptSigWithSignature(
                inputScript, signature.encodeToPeercoin(), sigIndex);
        txIn.setScriptSig(inputScript);

      } catch (ECKey.KeyIsEncryptedException e) {
        throw e;
      } catch (ECKey.MissingPrivateKeyException e) {
        log.warn("No private key in keypair for input {}", i);
      }
    }
    return true;
  }
예제 #4
0
 /**
  * Creates a scriptSig that can redeem a pay-to-pubkey output. If given signature is null,
  * incomplete scriptSig will be created with OP_0 instead of signature
  */
 public static Script createInputScript(@Nullable TransactionSignature signature) {
   byte[] sigBytes = signature != null ? signature.encodeToPeercoin() : new byte[] {};
   return new ScriptBuilder().data(sigBytes).build();
 }