/** * 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 createP2SHRedeemScript(); }
private Script createP2SHRedeemScript() { return ScriptBuilder.createCLTVPaymentChannelOutput(BigInteger.valueOf(getExpiryTime()), clientKey, serverKey); }
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; signP2SHInput(tx, Transaction.SigHash.NONE, true); signP2SHInput(tx, Transaction.SigHash.ALL, false);
@GuardedBy("lock") private void receiveContractMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1 || majorVersion == 2); checkState(step == InitStep.WAITING_ON_CONTRACT && msg.hasProvideContract()); log.info("Got contract, broadcasting and responding with CHANNEL_OPEN"); final Protos.ProvideContract providedContract = msg.getProvideContract(); if (majorVersion == 2) { state = new PaymentChannelV2ServerState(broadcaster, wallet, myKey, expireTime); checkState(providedContract.hasClientKey(), "ProvideContract didn't have a client key in protocol v2"); ((PaymentChannelV2ServerState)state).provideClientKey(providedContract.getClientKey().toByteArray()); } //TODO notify connection handler that timeout should be significantly extended as we wait for network propagation? final Transaction contract = wallet.getParams().getDefaultSerializer().makeTransaction(providedContract.getTx().toByteArray()); step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE; state.provideContract(contract) .addListener(new Runnable() { @Override public void run() { multisigContractPropogated(providedContract, contract.getHash()); } }, Threading.SAME_THREAD); }
@Override protected void verifyContract(final Transaction contract) { super.verifyContract(contract); // Check contract matches P2SH hash byte[] expected = getContractScript().getPubKeyHash(); byte[] actual = Utils.sha256hash160(createP2SHRedeemScript().getProgram()); if (!Arrays.equals(actual, expected)) { throw new VerificationException( "P2SH hash didn't match required contract - contract should be a CLTV micropayment channel to client and server in that order."); } }
serverV2State().provideClientKey(clientState.myKey.getPubKey());
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; signP2SHInput(tx, Transaction.SigHash.NONE, true, userKey); signP2SHInput(tx, Transaction.SigHash.ALL, false, userKey);
@GuardedBy("lock") private void receiveContractMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1 || majorVersion == 2); checkState(step == InitStep.WAITING_ON_CONTRACT && msg.hasProvideContract()); log.info("Got contract, broadcasting and responding with CHANNEL_OPEN"); final Protos.ProvideContract providedContract = msg.getProvideContract(); if (majorVersion == 2) { state = new PaymentChannelV2ServerState(broadcaster, wallet, myKey, expireTime); checkState(providedContract.hasClientKey(), "ProvideContract didn't have a client key in protocol v2"); ((PaymentChannelV2ServerState)state).provideClientKey(providedContract.getClientKey().toByteArray()); } //TODO notify connection handler that timeout should be significantly extended as we wait for network propagation? final Transaction contract = wallet.getParams().getDefaultSerializer().makeTransaction(providedContract.getTx().toByteArray()); step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE; state.provideContract(contract) .addListener(new Runnable() { @Override public void run() { multisigContractPropogated(providedContract, contract.getHash()); } }, Threading.SAME_THREAD); }
@Override protected void verifyContract(final Transaction contract) { super.verifyContract(contract); // Check contract matches P2SH hash byte[] expected = getContractScript().getPubKeyHash(); byte[] actual = Utils.sha256hash160(createP2SHRedeemScript().getProgram()); if (!Arrays.equals(actual, expected)) { throw new VerificationException( "P2SH hash didn't match required contract - contract should be a CLTV micropayment channel to client and server in that order."); } }
serverV2State().provideClientKey(clientState.myKey.getPubKey());
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; signP2SHInput(tx, Transaction.SigHash.NONE, true); signP2SHInput(tx, Transaction.SigHash.ALL, false);
@GuardedBy("lock") private void receiveContractMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1 || majorVersion == 2); checkState(step == InitStep.WAITING_ON_CONTRACT && msg.hasProvideContract()); log.info("Got contract, broadcasting and responding with CHANNEL_OPEN"); final Protos.ProvideContract providedContract = msg.getProvideContract(); if (majorVersion == 2) { state = new PaymentChannelV2ServerState(broadcaster, wallet, myKey, expireTime); checkState(providedContract.hasClientKey(), "ProvideContract didn't have a client key in protocol v2"); ((PaymentChannelV2ServerState)state).provideClientKey(providedContract.getClientKey().toByteArray()); } //TODO notify connection handler that timeout should be significantly extended as we wait for network propagation? final Transaction contract = wallet.getParams().getDefaultSerializer().makeTransaction(providedContract.getTx().toByteArray()); step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE; state.provideContract(contract) .addListener(new Runnable() { @Override public void run() { multisigContractPropogated(providedContract, contract.getHash()); } }, Threading.SAME_THREAD); }
@Override protected void verifyContract(final Transaction contract) { super.verifyContract(contract); // Check contract matches P2SH hash byte[] expected = getContractScript().getPubKeyHash(); byte[] actual = Utils.sha256hash160(createP2SHRedeemScript().getProgram()); if (!Arrays.equals(actual, expected)) { throw new VerificationException( "P2SH hash didn't match required contract - contract should be a CLTV micropayment channel to client and server in that order."); } }
@Override protected Script getSignedScript() { return createP2SHRedeemScript(); }
serverV2State().provideClientKey(myKey.getPubKey());
/** * 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; }
private Script createP2SHRedeemScript() { return ScriptBuilder.createCLTVPaymentChannelOutput(BigInteger.valueOf(getExpiryTime()), clientKey, serverKey); }
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; signP2SHInput(tx, Transaction.SigHash.NONE, true, userKey); signP2SHInput(tx, Transaction.SigHash.ALL, false, userKey);
@GuardedBy("lock") private void receiveContractMessage(Protos.TwoWayChannelMessage msg) throws VerificationException { checkState(majorVersion == 1 || majorVersion == 2); checkState(step == InitStep.WAITING_ON_CONTRACT && msg.hasProvideContract()); log.info("Got contract, broadcasting and responding with CHANNEL_OPEN"); final Protos.ProvideContract providedContract = msg.getProvideContract(); if (majorVersion == 2) { state = new PaymentChannelV2ServerState(broadcaster, wallet, myKey, expireTime); checkState(providedContract.hasClientKey(), "ProvideContract didn't have a client key in protocol v2"); ((PaymentChannelV2ServerState)state).provideClientKey(providedContract.getClientKey().toByteArray()); } //TODO notify connection handler that timeout should be significantly extended as we wait for network propagation? final Transaction contract = wallet.getParams().getDefaultSerializer().makeTransaction(providedContract.getTx().toByteArray()); step = InitStep.WAITING_ON_MULTISIG_ACCEPTANCE; state.provideContract(contract) .addListener(new Runnable() { @Override public void run() { multisigContractPropogated(providedContract, contract.getHash()); } }, Threading.SAME_THREAD); }