Java Code Examples for org.bitcoinj.crypto.TransactionSignature#anyoneCanPay()

The following examples show how to use org.bitcoinj.crypto.TransactionSignature#anyoneCanPay() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: PaymentChannelV1ClientState.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * <p>When the servers signature for the refund transaction is received, call this to verify it and sign the
 * complete refund ourselves.</p>
 * <p>
 * <p>If this does not throw an exception, we are secure against the loss of funds and can safely provide the server
 * with the multi-sig contract to lock in the agreement. In this case, both the multisig contract and the refund
 * transaction are automatically committed to wallet so that it can handle broadcasting the refund transaction at
 * the appropriate time if necessary.</p>
 */
public synchronized void provideRefundSignature(byte[] theirSignature, @Nullable KeyParameter userKey)
        throws VerificationException {
    checkNotNull(theirSignature);
    stateMachine.checkState(State.WAITING_FOR_SIGNED_REFUND);
    TransactionSignature theirSig = TransactionSignature.decodeFromBitcoin(theirSignature, true);
    if (theirSig.sigHashMode() != Transaction.SigHash.NONE || !theirSig.anyoneCanPay())
        throw new VerificationException("Refund signature was not SIGHASH_NONE|SIGHASH_ANYONECANPAY");
    // Sign the refund transaction ourselves.
    final TransactionOutput multisigContractOutput = multisigContract.getOutput(0);
    try {
        multisigScript = multisigContractOutput.getScriptPubKey();
    } catch (ScriptException e) {
        throw new RuntimeException(e);  // Cannot happen: we built this ourselves.
    }
    TransactionSignature ourSignature =
            refundTx.calculateSignature(0, myKey.maybeDecrypt(userKey),
                    multisigScript, Transaction.SigHash.ALL, false);
    // Insert the signatures.
    Script scriptSig = ScriptBuilder.createMultiSigInputScript(ourSignature, theirSig);
    log.info("Refund scriptSig: {}", scriptSig);
    log.info("Multi-sig contract scriptPubKey: {}", multisigScript);
    TransactionInput refundInput = refundTx.getInput(0);
    refundInput.setScriptSig(scriptSig);
    refundInput.verify(multisigContractOutput);
    stateMachine.transition(State.SAVE_STATE_IN_WALLET);
}
 
Example 2
Source File: PaymentChannelV1ClientState.java    From green_android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * <p>When the servers signature for the refund transaction is received, call this to verify it and sign the
 * complete refund ourselves.</p>
 *
 * <p>If this does not throw an exception, we are secure against the loss of funds and can safely provide the server
 * with the multi-sig contract to lock in the agreement. In this case, both the multisig contract and the refund
 * transaction are automatically committed to wallet so that it can handle broadcasting the refund transaction at
 * the appropriate time if necessary.</p>
 */
public synchronized void provideRefundSignature(byte[] theirSignature, @Nullable KeyParameter userKey)
        throws VerificationException {
    checkNotNull(theirSignature);
    stateMachine.checkState(State.WAITING_FOR_SIGNED_REFUND);
    TransactionSignature theirSig = TransactionSignature.decodeFromBitcoin(theirSignature, true);
    if (theirSig.sigHashMode() != Transaction.SigHash.NONE || !theirSig.anyoneCanPay())
        throw new VerificationException("Refund signature was not SIGHASH_NONE|SIGHASH_ANYONECANPAY");
    // Sign the refund transaction ourselves.
    final TransactionOutput multisigContractOutput = multisigContract.getOutput(0);
    try {
        multisigScript = multisigContractOutput.getScriptPubKey();
    } catch (ScriptException e) {
        throw new RuntimeException(e);  // Cannot happen: we built this ourselves.
    }
    TransactionSignature ourSignature =
            refundTx.calculateSignature(0, myKey.maybeDecrypt(userKey),
                    multisigScript, Transaction.SigHash.ALL, false);
    // Insert the signatures.
    Script scriptSig = ScriptBuilder.createMultiSigInputScript(ourSignature, theirSig);
    log.info("Refund scriptSig: {}", scriptSig);
    log.info("Multi-sig contract scriptPubKey: {}", multisigScript);
    TransactionInput refundInput = refundTx.getInput(0);
    refundInput.setScriptSig(scriptSig);
    refundInput.verify(multisigContractOutput);
    stateMachine.transition(State.SAVE_STATE_IN_WALLET);
}
 
Example 3
Source File: PaymentChannelV1ClientState.java    From GreenBits with GNU General Public License v3.0 5 votes vote down vote up
/**
 * <p>When the servers signature for the refund transaction is received, call this to verify it and sign the
 * complete refund ourselves.</p>
 *
 * <p>If this does not throw an exception, we are secure against the loss of funds and can safely provide the server
 * with the multi-sig contract to lock in the agreement. In this case, both the multisig contract and the refund
 * transaction are automatically committed to wallet so that it can handle broadcasting the refund transaction at
 * the appropriate time if necessary.</p>
 */
public synchronized void provideRefundSignature(byte[] theirSignature, @Nullable KeyParameter userKey)
        throws VerificationException {
    checkNotNull(theirSignature);
    stateMachine.checkState(State.WAITING_FOR_SIGNED_REFUND);
    TransactionSignature theirSig = TransactionSignature.decodeFromBitcoin(theirSignature, true);
    if (theirSig.sigHashMode() != Transaction.SigHash.NONE || !theirSig.anyoneCanPay())
        throw new VerificationException("Refund signature was not SIGHASH_NONE|SIGHASH_ANYONECANPAY");
    // Sign the refund transaction ourselves.
    final TransactionOutput multisigContractOutput = multisigContract.getOutput(0);
    try {
        multisigScript = multisigContractOutput.getScriptPubKey();
    } catch (ScriptException e) {
        throw new RuntimeException(e);  // Cannot happen: we built this ourselves.
    }
    TransactionSignature ourSignature =
            refundTx.calculateSignature(0, myKey.maybeDecrypt(userKey),
                    multisigScript, Transaction.SigHash.ALL, false);
    // Insert the signatures.
    Script scriptSig = ScriptBuilder.createMultiSigInputScript(ourSignature, theirSig);
    log.info("Refund scriptSig: {}", scriptSig);
    log.info("Multi-sig contract scriptPubKey: {}", multisigScript);
    TransactionInput refundInput = refundTx.getInput(0);
    refundInput.setScriptSig(scriptSig);
    refundInput.verify(multisigContractOutput);
    stateMachine.transition(State.SAVE_STATE_IN_WALLET);
}
 
Example 4
Source File: PaymentChannelServerState.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Called when the client provides us with a new signature and wishes to increment total payment by size.		+
 * Verifies the provided signature and only updates values if everything checks out.
 * If the new refundSize is not the lowest we have seen, it is simply ignored.
 *
 * @param refundSize     How many satoshis of the original contract are refunded to the client (the rest are ours)
 * @param signatureBytes The new signature spending the multi-sig contract to a new payment transaction
 * @return true if there is more value left on the channel, false if it is now fully used up.
 * @throws VerificationException If the signature does not verify or size is out of range (incl being rejected by the network as dust).
 */
public synchronized boolean incrementPayment(Coin refundSize, byte[] signatureBytes) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException {
    stateMachine.checkState(State.READY);
    checkNotNull(refundSize);
    checkNotNull(signatureBytes);
    TransactionSignature signature = TransactionSignature.decodeFromBitcoin(signatureBytes, true);
    // We allow snapping to zero for the payment amount because it's treated specially later, but not less than
    // the dust level because that would prevent the transaction from being relayed/mined.
    final boolean fullyUsedUp = refundSize.equals(Coin.ZERO);
    Coin newValueToMe = getTotalValue().subtract(refundSize);
    if (newValueToMe.signum() < 0)
        throw new ValueOutOfRangeException("Attempt to refund more than the contract allows.");
    if (newValueToMe.compareTo(bestValueToMe) < 0)
        throw new ValueOutOfRangeException("Attempt to roll back payment on the channel.");

    SendRequest req = makeUnsignedChannelContract(newValueToMe);

    if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
        throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");

    // Get the wallet's copy of the contract (ie with confidence information), if this is null, the wallet
    // was not connected to the peergroup when the contract was broadcast (which may cause issues down the road, and
    // disables our double-spend check next)
    Transaction walletContract = wallet.getTransaction(contract.getHash());
    checkNotNull(walletContract, "Wallet did not contain multisig contract {} after state was marked READY", contract.getHash());

    // Note that we check for DEAD state here, but this test is essentially useless in production because we will
    // miss most double-spends due to bloom filtering right now anyway. This will eventually fixed by network-wide
    // double-spend notifications, so we just wait instead of attempting to add all dependant outpoints to our bloom
    // filters (and probably missing lots of edge-cases).
    if (walletContract.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.DEAD) {
        close();
        throw new VerificationException("Multisig contract was double-spent");
    }

    Transaction.SigHash mode;
    // If the client doesn't want anything back, they shouldn't sign any outputs at all.
    if (fullyUsedUp)
        mode = Transaction.SigHash.NONE;
    else
        mode = Transaction.SigHash.SINGLE;

    if (signature.sigHashMode() != mode || !signature.anyoneCanPay())
        throw new VerificationException("New payment signature was not signed with the right SIGHASH flags.");

    // Now check the signature is correct.
    // Note that the client must sign with SIGHASH_{SINGLE/NONE} | SIGHASH_ANYONECANPAY to allow us to add additional
    // inputs (in case we need to add significant fee, or something...) and any outputs we want to pay to.
    Sha256Hash sighash = req.tx.hashForSignature(0, getSignedScript(), mode, true);

    if (!getClientKey().verify(sighash, signature))
        throw new VerificationException("Signature does not verify on tx\n" + req.tx);
    bestValueToMe = newValueToMe;
    bestValueSignature = signatureBytes;
    updateChannelInWallet();
    return !fullyUsedUp;
}
 
Example 5
Source File: PaymentChannelServerState.java    From green_android with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Called when the client provides us with a new signature and wishes to increment total payment by size.		+
 * Verifies the provided signature and only updates values if everything checks out.
 * If the new refundSize is not the lowest we have seen, it is simply ignored.
 *
 * @param refundSize How many satoshis of the original contract are refunded to the client (the rest are ours)
 * @param signatureBytes The new signature spending the multi-sig contract to a new payment transaction
 * @throws VerificationException If the signature does not verify or size is out of range (incl being rejected by the network as dust).
 * @return true if there is more value left on the channel, false if it is now fully used up.
 */
public synchronized boolean incrementPayment(Coin refundSize, byte[] signatureBytes) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException {
    stateMachine.checkState(State.READY);
    checkNotNull(refundSize);
    checkNotNull(signatureBytes);
    TransactionSignature signature = TransactionSignature.decodeFromBitcoin(signatureBytes, true);
    // We allow snapping to zero for the payment amount because it's treated specially later, but not less than
    // the dust level because that would prevent the transaction from being relayed/mined.
    final boolean fullyUsedUp = refundSize.equals(Coin.ZERO);
    Coin newValueToMe = getTotalValue().subtract(refundSize);
    if (newValueToMe.signum() < 0)
        throw new ValueOutOfRangeException("Attempt to refund more than the contract allows.");
    if (newValueToMe.compareTo(bestValueToMe) < 0)
        throw new ValueOutOfRangeException("Attempt to roll back payment on the channel.");

    SendRequest req = makeUnsignedChannelContract(newValueToMe);

    if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
        throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");

    // Get the wallet's copy of the contract (ie with confidence information), if this is null, the wallet
    // was not connected to the peergroup when the contract was broadcast (which may cause issues down the road, and
    // disables our double-spend check next)
    Transaction walletContract = wallet.getTransaction(contract.getHash());
    checkNotNull(walletContract, "Wallet did not contain multisig contract {} after state was marked READY", contract.getHash());

    // Note that we check for DEAD state here, but this test is essentially useless in production because we will
    // miss most double-spends due to bloom filtering right now anyway. This will eventually fixed by network-wide
    // double-spend notifications, so we just wait instead of attempting to add all dependant outpoints to our bloom
    // filters (and probably missing lots of edge-cases).
    if (walletContract.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.DEAD) {
        close();
        throw new VerificationException("Multisig contract was double-spent");
    }

    Transaction.SigHash mode;
    // If the client doesn't want anything back, they shouldn't sign any outputs at all.
    if (fullyUsedUp)
        mode = Transaction.SigHash.NONE;
    else
        mode = Transaction.SigHash.SINGLE;

    if (signature.sigHashMode() != mode || !signature.anyoneCanPay())
        throw new VerificationException("New payment signature was not signed with the right SIGHASH flags.");

    // Now check the signature is correct.
    // Note that the client must sign with SIGHASH_{SINGLE/NONE} | SIGHASH_ANYONECANPAY to allow us to add additional
    // inputs (in case we need to add significant fee, or something...) and any outputs we want to pay to.
    Sha256Hash sighash = req.tx.hashForSignature(0, getSignedScript(), mode, true);

    if (!getClientKey().verify(sighash, signature))
        throw new VerificationException("Signature does not verify on tx\n" + req.tx);
    bestValueToMe = newValueToMe;
    bestValueSignature = signatureBytes;
    updateChannelInWallet();
    return !fullyUsedUp;
}
 
Example 6
Source File: PaymentChannelServerState.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Called when the client provides us with a new signature and wishes to increment total payment by size.		+
 * Verifies the provided signature and only updates values if everything checks out.
 * If the new refundSize is not the lowest we have seen, it is simply ignored.
 *
 * @param refundSize How many satoshis of the original contract are refunded to the client (the rest are ours)
 * @param signatureBytes The new signature spending the multi-sig contract to a new payment transaction
 * @throws VerificationException If the signature does not verify or size is out of range (incl being rejected by the network as dust).
 * @return true if there is more value left on the channel, false if it is now fully used up.
 */
public synchronized boolean incrementPayment(Coin refundSize, byte[] signatureBytes) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException {
    stateMachine.checkState(State.READY);
    checkNotNull(refundSize);
    checkNotNull(signatureBytes);
    TransactionSignature signature = TransactionSignature.decodeFromBitcoin(signatureBytes, true);
    // We allow snapping to zero for the payment amount because it's treated specially later, but not less than
    // the dust level because that would prevent the transaction from being relayed/mined.
    final boolean fullyUsedUp = refundSize.equals(Coin.ZERO);
    Coin newValueToMe = getTotalValue().subtract(refundSize);
    if (newValueToMe.signum() < 0)
        throw new ValueOutOfRangeException("Attempt to refund more than the contract allows.");
    if (newValueToMe.compareTo(bestValueToMe) < 0)
        throw new ValueOutOfRangeException("Attempt to roll back payment on the channel.");

    SendRequest req = makeUnsignedChannelContract(newValueToMe);

    if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
        throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");

    // Get the wallet's copy of the contract (ie with confidence information), if this is null, the wallet
    // was not connected to the peergroup when the contract was broadcast (which may cause issues down the road, and
    // disables our double-spend check next)
    Transaction walletContract = wallet.getTransaction(contract.getHash());
    checkNotNull(walletContract, "Wallet did not contain multisig contract {} after state was marked READY", contract.getHash());

    // Note that we check for DEAD state here, but this test is essentially useless in production because we will
    // miss most double-spends due to bloom filtering right now anyway. This will eventually fixed by network-wide
    // double-spend notifications, so we just wait instead of attempting to add all dependant outpoints to our bloom
    // filters (and probably missing lots of edge-cases).
    if (walletContract.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.DEAD) {
        close();
        throw new VerificationException("Multisig contract was double-spent");
    }

    Transaction.SigHash mode;
    // If the client doesn't want anything back, they shouldn't sign any outputs at all.
    if (fullyUsedUp)
        mode = Transaction.SigHash.NONE;
    else
        mode = Transaction.SigHash.SINGLE;

    if (signature.sigHashMode() != mode || !signature.anyoneCanPay())
        throw new VerificationException("New payment signature was not signed with the right SIGHASH flags.");

    // Now check the signature is correct.
    // Note that the client must sign with SIGHASH_{SINGLE/NONE} | SIGHASH_ANYONECANPAY to allow us to add additional
    // inputs (in case we need to add significant fee, or something...) and any outputs we want to pay to.
    Sha256Hash sighash = req.tx.hashForSignature(0, getSignedScript(), mode, true);

    if (!getClientKey().verify(sighash, signature))
        throw new VerificationException("Signature does not verify on tx\n" + req.tx);
    bestValueToMe = newValueToMe;
    bestValueSignature = signatureBytes;
    updateChannelInWallet();
    return !fullyUsedUp;
}