dear mimblewimblers,

I'd like to propose a potential alternative way to implement relative
time locks. It possibly qualifies as a "crazy idea" as Antioch alluded
to below. It can be thought of as a negative trigger.

I propose to call it a "No Such Kernel Recently" or NSKR lock.
Suppose we have transaction A that might appear on chain at an unknown
height in the future, and a transaction B, spending A's output, that
should only happen at least a day after A. We can refer to kernel A
inside kernel B and require that inclusion of B in a block at height h
is invalid if kernel A appears at any height from h-1440 up to (and
including) h.
Compared to a positive trigger that would require kernel A to have
been included at least 1440 blocks earlier, the obvious difference is
that NSKR doesn't require checking the entire kernel history from
height 0 to height h-1440, which is a big gain in efficiency and
allows kernel history verification to proceed with a small moving
window.

It may appear to have as a downside a seeming violation of the
following principle that Andrew brought up earlier:

> Agreed, I think we want to copy Bitcoin's attitude of "transactions, once 
> valid, never stop being valid" although the reverse is allowable.

However, for B to be valid in the first place, by construction, A must
already be on chain to provide B with valid inputs. So B cannot be
invalidated by the appearance of A.

It thus seems that NSKR provide an efficient means to implement
relative time locks. Feedback welcome.

regards,
-John

> Your email matches the idea of "triggers" that I originally proposed
> for enabling relative timelocks back in Jan 2017:
> https://lists.launchpad.net/mimblewimble/msg00025.html
>
> The conclusion that Andrew Poelstra and I came to back then was the
> same: kernels (previously referred to as "excess values") are the
> logical place for it.
>
> >We would need to maintain an unpruneable index of all kernels on all nodes.
>
> This may not be practical in terms of bandwidth (and maybe adds
> complications for IBD?), but the transaction that depends on the
> inclusion of a kernel could be accompanied by an SPV proof to that
> kernel. It would be in the interest of the sender to reference the
> "first seen" one.
>
> >We would need to handle the case of it being added prematurely
>
> Premature to whom? Triggering the countdown of a relative timelock
> would imply some kind of disagreement that needs to be resolved by the
> blockchain, so it will always be premature to the party that is being
> forced to react.
>
> >we have the ability to actively monitor for and observe this on-chain
>
> Yes, that seems like an absolute prerequisite. If triggering the
> timelock is not detectable, then the other party in the channel cannot
> respond to it.
>
> >I want to encourage anyone with _any_ ideas (maybe even the particularly 
> >crazy ones)

> It seems inherent that at least *something* needs to noticeably appear
> or change in order to trigger the countdown. Here's an idea that I
> think is absolutely terrible but fits the 'crazy' bill. You could use
> the relative timelock capabilities of a different blockchain (e.g.
> Bitcoin) to force someone (yes, they'd need to have equivalent value
> locked up in that chain...) to reveal an RSA timelock puzzle,
> triggering the countdown. Based on Ethan Heilman's idea:

> -- Ruben Somsen
> >
> > The Grin team is doing some brainstorming around how best to implement 
> > "relative locktimes" and we wanted to open this up to the wider community 
> > to see if anyone has additional thoughts and ideas around this.
> >
> > To clarify - this discussion is about "transaction locktimes" and not 
> > "output locktimes".
> > This is a minimum block height (relative or absolute) that a tx will be 
> > accepted after (and invalid prior to this height).
> > This is not a way to lock an output on-chain and make it unspendable before 
> > a certain height (although these concepts may be closely related).
> >
> > Grin currently has "absolute locktimes".
> > Each tx kernel includes a lock_height that specifies the earliest height 
> > this tx can be included.
> > We sign the lock_height alongside the fee in each tx kernel. This 
> > lock_height can be thought of as roughly analogous to the concept of 
> > nLockTime in Bitcoin.
> >
> > What we want is a way to add "relative locktimes". Presumably by referring 
> > to some prior piece of data on-chain. Bitcoin does this with nSequence 
> > field on inputs (a relative number of blocks since the output being spent).
> >
> > The problem with this in Grin is we don't really have inputs. They are not 
> > stored in the blockchain. An input in Grin is literally just a reference to 
> > a prior unspent output.
> > Once these txs are included in a block the inputs are effectively thrown 
> > away (along with the now spent outputs). All we maintain is the UTXO set 
> > and the tx kernels themselves.
> >
> > Which suggests that if we want to refer to some prior piece of data then we 
> > refer to either -
> >   * a prior (unspent) output, or
> >   * a prior tx kernel
> >
> > Note: We cannot simply refer to a prior block because we need to refer to 
> > something that may _not yet_ exist on-chain. We want to be able to create 
> > and sign two txs, one with a lockheight relative to the other before either 
> > has been broadcast and confirmed in a block.
> >
> > Prior (Uspent) outputs:
> > The benefit of referring to a prior output is we enforce uniqueness across 
> > the UTXO set
> > so we can be confident we are referring to the correct prior one, avoiding 
> > any ambiguity around the "relative to x at height h".
> >
> > The problem with outputs though is nodes only maintain data relating to 
> > _unspent_ outputs (the UTXO set).
> > Spent outputs are removed and effectively act as if they never existed. 
> > This is a core tenet of the scalability (and privacy) of MW.
> > So if we refer to an output we appear to be limited to only referring to an 
> > _unspent_ output.
> > Which is fine initially, you create two txs, one with a kernel referencing 
> > an output in the earlier tx. But then things get complicated if the 
> > referenced output gets spent during (or even before) the timelocked period.
> >
> > Prior kernels:
> > Kernels live forever (at least today in Grin).
> > Referencing a kernel from another kernel is "cleaner" (same MMR) than 
> > having a kernel reference an output (across two MMRs).
> > The problem though is that kernels live forever.
> > If we need to enforce uniqueness we need to do it across the global set of 
> > all kernels.
> > We would need to maintain an unpruneable index of all kernels on all nodes.
> > And the kernel set is only going to grow ever larger.
> >
> > So we would like to be able to implement this without relying on an index 
> > of all kernels.
> >
> > We are currently thinking through a couple of variations of this - allow 
> > non-unique kernels and refer to a prior kernel using either "first seen" or 
> > "last seen" semantics to resolve ambiguity.
> >
> > "Last seen" would appear to introduce a vector for denial-of-service.
> > A mischievous actor could easily craft txs repeatedly (re-)adding a 
> > duplicate kernel, forcing the relative locktime to block indefinitely.
> >
> > "First seen" avoids this problem, we have more control (but not complete 
> > control) over when the first instance of a given kernel is added. We would 
> > need to handle the case of it being added prematurely but we have the 
> > ability to actively monitor for and observe this on-chain.
> >
> >
> > This is basically where we are at right now with "relative locktimes" -
> >   * We (think) we need to refer to some prior piece of data on chain
> >     * n blocks after some x appearing at block height h
> >   * We want the flexibility to reference something _not yet_ on chain
> >     * This rules out simply referencing a prior block header
> >   * All we have to play with are UTXOs and kernels
> >   * We enforce uniqueness across the UTXO set
> >   * We would like to avoid needing to enforce uniqueness across the full 
> > kernel set
> >   * We would like to avoid all nodes needing to maintain an index over all 
> > kernels
> >
> >
> > What are we missing here? Is there some subtle thing we can do to allow for 
> > a simple "relative locktime" imnplementation?
> > Is there a way to do this avoiding a reference to either a kernel or an 
> > output?
> >
> >
> > Thoughts and feedback please!
> > I want to encourage anyone with _any_ ideas (maybe even the particularly 
> > crazy ones) to chime in here.
> > We can move it to the forum if we need to.
> >
> > — Antioch (and the rest of the Grin team).

-- 
Mailing list: https://launchpad.net/~mimblewimble
Post to     : mimblewimble@lists.launchpad.net
Unsubscribe : https://launchpad.net/~mimblewimble
More help   : https://help.launchpad.net/ListHelp

Reply via email to