/** * Gets the canonical {@link PaymentChannelServerState} object for this channel, either by returning an existing one * or by creating a new one. * * @param wallet The wallet which holds the {@link PaymentChannelServerState} in which this is saved and which will * be used to complete transactions * @param broadcaster The {@link TransactionBroadcaster} which will be used to broadcast contract/payment transactions. */ public synchronized PaymentChannelServerState getOrCreateState(Wallet wallet, TransactionBroadcaster broadcaster) throws VerificationException { if (state == null) { switch (majorVersion) { case 1: state = new PaymentChannelV1ServerState(this, wallet, broadcaster); break; case 2: state = new PaymentChannelV2ServerState(this, wallet, broadcaster); break; default: throw new IllegalStateException("Invalid version number found"); } } checkArgument(wallet == state.wallet); return state; }
@Override protected Script getSignedScript() { return getContractScript(); }
/** * Gets the client's refund transaction which they can spend to get the entire channel value back if it reaches its * lock time. */ public synchronized long getRefundTransactionUnlockTime() { checkState(getState().compareTo(State.WAITING_FOR_MULTISIG_CONTRACT) > 0 && getState() != State.ERROR); return refundTransactionUnlockTimeSecs; } }
wallet.getExtensions().get(StoredPaymentChannelServerStates.EXTENSION_ID); if (getState().compareTo(State.CLOSING) >= 0) return closedFuture; if (getState().ordinal() < State.READY.ordinal()) { log.error("Attempt to settle channel in state " + getState()); stateMachine.transition(State.CLOSED); closedFuture.set(null); return closedFuture; if (getState() != State.READY) { log.warn("Failed attempt to settle a channel in state " + getState()); return closedFuture; SendRequest req = makeUnsignedChannelContract(bestValueToMe); tx = req.tx; signMultisigInput(tx, Transaction.SigHash.NONE, true, userKey); signMultisigInput(tx, Transaction.SigHash.ALL, false, userKey);
@GuardedBy("lock") private void receiveRefundMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1); checkState(step == InitStep.WAITING_ON_UNSIGNED_REFUND && msg.hasProvideRefund()); log.info("Got refund transaction, returning signature"); Protos.ProvideRefund providedRefund = msg.getProvideRefund(); state = new PaymentChannelV1ServerState(broadcaster, wallet, myKey, expireTime); // We can cast to V1 state since this state is only used in the V1 protocol byte[] signature = ((PaymentChannelV1ServerState) state) .provideRefundTransaction(wallet.getParams().getDefaultSerializer().makeTransaction(providedRefund.getTx().toByteArray()), providedRefund.getMultisigKey().toByteArray()); step = InitStep.WAITING_ON_CONTRACT; Protos.ReturnRefund.Builder returnRefundBuilder = Protos.ReturnRefund.newBuilder() .setSignature(ByteString.copyFrom(signature)); conn.sendToClient(Protos.TwoWayChannelMessage.newBuilder() .setReturnRefund(returnRefundBuilder) .setType(Protos.TwoWayChannelMessage.MessageType.RETURN_REFUND) .build()); }
refund.addOutput(Coin.ZERO, new ECKey().toAddress(PARAMS)); try { serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); fail(); } catch (VerificationException e) { refund.addInput(new TransactionInput(PARAMS, refund, new byte[]{}, new TransactionOutPoint(PARAMS, 42, refund.getHash()))); try { serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); fail(); } catch (VerificationException e) { refund.setLockTime(0); try { serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); fail(); } catch (VerificationException e) { refund.getInput(0).setSequenceNumber(TransactionInput.NO_SEQUENCE); try { serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); fail(); } catch (VerificationException e) { byte[] refundSig = serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); try { serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); fail(); } catch (IllegalStateException e) {
wallet.getExtensions().get(StoredPaymentChannelServerStates.EXTENSION_ID); if (getState().compareTo(State.CLOSING) >= 0) return closedFuture; if (getState().ordinal() < State.READY.ordinal()) { log.error("Attempt to settle channel in state " + getState()); stateMachine.transition(State.CLOSED); closedFuture.set(null); return closedFuture; if (getState() != State.READY) { log.warn("Failed attempt to settle a channel in state " + getState()); return closedFuture; SendRequest req = makeUnsignedChannelContract(bestValueToMe); tx = req.tx; signMultisigInput(tx, Transaction.SigHash.NONE, true); signMultisigInput(tx, Transaction.SigHash.ALL, false);
@GuardedBy("lock") private void receiveRefundMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1); checkState(step == InitStep.WAITING_ON_UNSIGNED_REFUND && msg.hasProvideRefund()); log.info("Got refund transaction, returning signature"); Protos.ProvideRefund providedRefund = msg.getProvideRefund(); state = new PaymentChannelV1ServerState(broadcaster, wallet, myKey, expireTime); // We can cast to V1 state since this state is only used in the V1 protocol byte[] signature = ((PaymentChannelV1ServerState) state) .provideRefundTransaction(wallet.getParams().getDefaultSerializer().makeTransaction(providedRefund.getTx().toByteArray()), providedRefund.getMultisigKey().toByteArray()); step = InitStep.WAITING_ON_CONTRACT; Protos.ReturnRefund.Builder returnRefundBuilder = Protos.ReturnRefund.newBuilder() .setSignature(ByteString.copyFrom(signature)); conn.sendToClient(Protos.TwoWayChannelMessage.newBuilder() .setReturnRefund(returnRefundBuilder) .setType(Protos.TwoWayChannelMessage.MessageType.RETURN_REFUND) .build()); }
if (useRefunds()) { refund = new Transaction(PARAMS, clientV1State().getIncompleteRefundTransaction().bitcoinSerialize()); byte[] refundSig = serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); assertEquals(PaymentChannelServerState.State.WAITING_FOR_MULTISIG_CONTRACT, serverState.getState());
wallet.getExtensions().get(StoredPaymentChannelServerStates.EXTENSION_ID); if (getState().compareTo(State.CLOSING) >= 0) return closedFuture; if (getState().ordinal() < State.READY.ordinal()) { log.error("Attempt to settle channel in state " + getState()); stateMachine.transition(State.CLOSED); closedFuture.set(null); return closedFuture; if (getState() != State.READY) { log.warn("Failed attempt to settle a channel in state " + getState()); return closedFuture; SendRequest req = makeUnsignedChannelContract(bestValueToMe); tx = req.tx; signMultisigInput(tx, Transaction.SigHash.NONE, true, userKey); signMultisigInput(tx, Transaction.SigHash.ALL, false, userKey);
@GuardedBy("lock") private void receiveRefundMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1); checkState(step == InitStep.WAITING_ON_UNSIGNED_REFUND && msg.hasProvideRefund()); log.info("Got refund transaction, returning signature"); Protos.ProvideRefund providedRefund = msg.getProvideRefund(); state = new PaymentChannelV1ServerState(broadcaster, wallet, myKey, expireTime); // We can cast to V1 state since this state is only used in the V1 protocol byte[] signature = ((PaymentChannelV1ServerState) state) .provideRefundTransaction(wallet.getParams().getDefaultSerializer().makeTransaction(providedRefund.getTx().toByteArray()), providedRefund.getMultisigKey().toByteArray()); step = InitStep.WAITING_ON_CONTRACT; Protos.ReturnRefund.Builder returnRefundBuilder = Protos.ReturnRefund.newBuilder() .setSignature(ByteString.copyFrom(signature)); conn.sendToClient(Protos.TwoWayChannelMessage.newBuilder() .setReturnRefund(returnRefundBuilder) .setType(Protos.TwoWayChannelMessage.MessageType.RETURN_REFUND) .build()); }
@Override protected Script getSignedScript() { return getContractScript(); }
byte[] refundSig = serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); assertEquals(PaymentChannelServerState.State.WAITING_FOR_MULTISIG_CONTRACT, serverState.getState());
/** * Gets the canonical {@link PaymentChannelServerState} object for this channel, either by returning an existing one * or by creating a new one. * * @param wallet The wallet which holds the {@link PaymentChannelServerState} in which this is saved and which will * be used to complete transactions * @param broadcaster The {@link TransactionBroadcaster} which will be used to broadcast contract/payment transactions. */ public synchronized PaymentChannelServerState getOrCreateState(Wallet wallet, TransactionBroadcaster broadcaster) throws VerificationException { if (state == null) { switch (majorVersion) { case 1: state = new PaymentChannelV1ServerState(this, wallet, broadcaster); break; case 2: state = new PaymentChannelV2ServerState(this, wallet, broadcaster); break; default: throw new IllegalStateException("Invalid version number found"); } } checkArgument(wallet == state.wallet); return state; }
/** * Gets the client's refund transaction which they can spend to get the entire channel value back if it reaches its * lock time. */ public synchronized long getRefundTransactionUnlockTime() { checkState(getState().compareTo(State.WAITING_FOR_MULTISIG_CONTRACT) > 0 && getState() != State.ERROR); return refundTransactionUnlockTimeSecs; } }
wallet.getExtensions().get(StoredPaymentChannelServerStates.EXTENSION_ID); if (getState().compareTo(State.CLOSING) >= 0) return closedFuture; if (getState().ordinal() < State.READY.ordinal()) { log.error("Attempt to settle channel in state " + getState()); stateMachine.transition(State.CLOSED); closedFuture.set(null); return closedFuture; if (getState() != State.READY) { log.warn("Failed attempt to settle a channel in state " + getState()); return closedFuture; SendRequest req = makeUnsignedChannelContract(bestValueToMe); tx = req.tx; signMultisigInput(tx, Transaction.SigHash.NONE, true); signMultisigInput(tx, Transaction.SigHash.ALL, false);
@GuardedBy("lock") private void receiveRefundMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1); checkState(step == InitStep.WAITING_ON_UNSIGNED_REFUND && msg.hasProvideRefund()); log.info("Got refund transaction, returning signature"); Protos.ProvideRefund providedRefund = msg.getProvideRefund(); state = new PaymentChannelV1ServerState(broadcaster, wallet, myKey, expireTime); // We can cast to V1 state since this state is only used in the V1 protocol byte[] signature = ((PaymentChannelV1ServerState) state) .provideRefundTransaction(wallet.getParams().getDefaultSerializer().makeTransaction(providedRefund.getTx().toByteArray()), providedRefund.getMultisigKey().toByteArray()); step = InitStep.WAITING_ON_CONTRACT; Protos.ReturnRefund.Builder returnRefundBuilder = Protos.ReturnRefund.newBuilder() .setSignature(ByteString.copyFrom(signature)); conn.sendToClient(Protos.TwoWayChannelMessage.newBuilder() .setReturnRefund(returnRefundBuilder) .setType(Protos.TwoWayChannelMessage.MessageType.RETURN_REFUND) .build()); }
@Override protected Script getSignedScript() { return getContractScript(); }
byte[] refundSig = serverV1State().provideRefundTransaction(refund, myKey.getPubKey()); assertEquals(PaymentChannelServerState.State.WAITING_FOR_MULTISIG_CONTRACT, serverState.getState());
/** * Gets the canonical {@link PaymentChannelServerState} object for this channel, either by returning an existing one * or by creating a new one. * * @param wallet The wallet which holds the {@link PaymentChannelServerState} in which this is saved and which will * be used to complete transactions * @param broadcaster The {@link TransactionBroadcaster} which will be used to broadcast contract/payment transactions. */ public synchronized PaymentChannelServerState getOrCreateState(Wallet wallet, TransactionBroadcaster broadcaster) throws VerificationException { if (state == null) { switch (majorVersion) { case 1: state = new PaymentChannelV1ServerState(this, wallet, broadcaster); break; case 2: state = new PaymentChannelV2ServerState(this, wallet, broadcaster); break; default: throw new IllegalStateException("Invalid version number found"); } } checkArgument(wallet == state.wallet); return state; }