Commit 8d6d0e2e authored by mruddy's avatar mruddy Committed by Andreas Schildbach

Update payment channel sequence numbers for time locked transactions with BIP68 and BIP125 in mind.

parent 95052276
......@@ -151,7 +151,9 @@ public class PaymentChannelV1ClientState extends PaymentChannelClientState {
// in future as it breaks the intended design of timelocking/tx replacement, but for now it simplifies this
// specific protocol somewhat.
refundTx = new Transaction(params);
refundTx.addInput(multisigOutput).setSequenceNumber(0); // Allow replacement when it's eventually reactivated.
// don't disable lock time. the sequence will be included in the server's signature and thus won't be changeable.
// by using this sequence value, we avoid extra full replace-by-fee and relative lock time processing.
refundTx.addInput(multisigOutput).setSequenceNumber(TransactionInput.NO_SEQUENCE - 1L);
refundTx.setLockTime(expiryTime);
if (totalValue.compareTo(Coin.CENT) < 0 && Context.get().isEnsureMinRequiredFee()) {
// Must pay min fee.
......
......@@ -125,9 +125,9 @@ public class PaymentChannelV1ServerState extends PaymentChannelServerState {
// Verify that the refund transaction has a single input (that we can fill to sign the multisig output).
if (refundTx.getInputs().size() != 1)
throw new VerificationException("Refund transaction does not have exactly one input");
// Verify that the refund transaction has a time lock on it and a sequence number of zero.
if (refundTx.getInput(0).getSequenceNumber() != 0)
throw new VerificationException("Refund transaction's input's sequence number is non-0");
// Verify that the refund transaction has a time lock on it and a sequence number that does not disable lock time.
if (refundTx.getInput(0).getSequenceNumber() == TransactionInput.NO_SEQUENCE)
throw new VerificationException("Refund transaction's input's sequence number disables lock time");
if (refundTx.getLockTime() < minExpireTime)
throw new VerificationException("Refund transaction has a lock time too soon");
// Verify the transaction has one output (we don't care about its contents, its up to the client)
......
......@@ -119,13 +119,12 @@ public class PaymentChannelV2ClientState extends PaymentChannelClientState {
contract = req.tx;
// Build a refund transaction that protects us in the case of a bad server that's just trying to cause havoc
// by locking up peoples money (perhaps as a precursor to a ransom attempt). We time lock it so the server
// has an assurance that we cannot take back our money by claiming a refund before the channel closes - this
// relies on the fact that since Bitcoin 0.8 time locked transactions are non-final. This will need to change
// in future as it breaks the intended design of timelocking/tx replacement, but for now it simplifies this
// specific protocol somewhat.
// by locking up peoples money (perhaps as a precursor to a ransom attempt). We time lock it because the
// CheckLockTimeVerify opcode requires a lock time to be specified and the input to have a non-final sequence
// number (so that the lock time is not disabled).
refundTx = new Transaction(params);
refundTx.addInput(contract.getOutput(0)).setSequenceNumber(0); // Allow replacement when it's eventually reactivated.
// by using this sequence value, we avoid extra full replace-by-fee and relative lock time processing.
refundTx.addInput(contract.getOutput(0)).setSequenceNumber(TransactionInput.NO_SEQUENCE - 1L);
refundTx.setLockTime(expiryTime);
if (totalValue.compareTo(Coin.CENT) < 0 && Context.get().isEnsureMinRequiredFee()) {
// Must pay min fee.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment