CAP: 0011
Title: Relative Account Freeze
Author: Jeremy Rubin
Status: Draft
Created: 2018-11-14
Discussion: https://github.com/stellar/stellar-protocol/issues/90
Protocol version: TBD
This CAP introduces a locking signer which allows for relative time locks of accounts.
In stellar, transactions are allowed to condition their validity based on time. However, because time is defined to be absolute, and the time at which events are confirmed into the ledger are non-deterministic, this makes it difficult to reason about the scheduling of events in complex contracts. Furthermore, transaction validity ranges don't exclude the possibility of another transaction with a different time range being availabke,
To address this partially, we introduce the notion of a time lock at the account level which may be absolute or relative. This construct provides flexibility for contract designers to sequence time based events easily and circumvent the need for periodic updates in time based protocols.
Currently, transactions may specify a valid after and valid before date range. However, this range is absolute so it does not permit protocols that specify for some action to happen after another action without knowledge of the exact timing. This makes writing channel protocols difficult as they typically require periodic updates. See here.
A relative timeout signer
enum SignerKeyType
{
SIGNER_KEY_TYPE_ED25519 = KEY_TYPE_ED25519,
SIGNER_KEY_TYPE_PRE_AUTH_TX = KEY_TYPE_PRE_AUTH_TX,
SIGNER_KEY_TYPE_HASH_X = KEY_TYPE_HASH_X,
SIGNER_KEY_TYPE_TIMEOUT = 11
};
enum TIMEOUT_FLAGS {
TIMEOUT_FLAGS_SEQUENCE_RELATIVE = 1,
TIMEOUT_FLAGS_CLOCK_RELATIVE = 1<<1,
TIMEOUT_FLAGS_REMOVABLE = 1<<2,
TIMEOUT_FLAGS_NO_AUTOREMOVE = 1<<3,
TIMEOUT_FLAGS_ONLY_BUMPSEQ = 1<<4,
TIMEOUT_FLAGS_NO_BUMPSEQ = 1<<5,
TIMEOUT_FLAGS_ALLOW_HI = 1<<6,
TIMEOUT_FLAGS_ALLOW_MID = 1<<7,
TIMEOUT_FLAGS_ALLOW_LOW = 1<<8,
};
union SignerKey switch (SignerKeyType type)
{
case SIGNER_KEY_TYPE_ED25519:
uint256 ed25519;
case SIGNER_KEY_TYPE_PRE_AUTH_TX:
/* SHA-256 Hash of TransactionSignaturePayload structure */
uint256 preAuthTx;
case SIGNER_KEY_TYPE_HASH_X:
/* Hash of random 256 bit preimage X */
uint256 hashX;
case SIGNER_KEY_TYPE_TIMEOUT:
struct {
uint64 flags;
int64 original_closeTime;
int64 actual_closeTime;
uint32 original_ledgerSeq;
uint32 actual_ledgerSeq;
} locktill;
};
When a timeout key is added to an account, the accounts seuence number may not
be increased until the current ledger sequence and most recent close time are
both greater than or equal to the times specified in the
SIGNER_KEY_TYPE_TIMEOUT
. The actual_
fields may be set to an arbitrary value
and are filled in upon receipt of the relative locktime with the actual computed
time. The original_
fields are set to the actual_
fields value before they are modified. Transactions where the account is not the source may still succeed while
the timeout is present unless otherwise specified.
If the relative seq and time flags are set then when the entry is added the timeout is computed relative to the execution time of the transaction adding it. For example, were it to be 100 ledgers relatively and it was added at ledger 64534, then the next sequence adjusting transaction could happen at ledger 64634.
If the REMOVABLE flag is set, then the timeout may be removed by a transaction which has a different source account. If it is not set, the timeout may not be removed until it has matured.
If NO_AUTOREMOVE
is set, then the key does not delete itself automatically off
of the account once satisfied. If it is unset, the signer removes itself
automatically once satisfied. To manually remove a relative signer, it should be
referred to with the original_
fields set to the acutal_
value it was set to be
when added.
If ONLY_BUMPSEQ
is set, then the only operation that may use the account as a source
is a BUMPSEQ.
If NO_BUMPSEQ
is set, then BUMPSEQ may not use the account as a source of an operation.
If ALLOW_MID
or ALLOW_HI
are set, then the timeout may be overrided by a MID
or HIGH threshold set of signers. ALLOW_LOW
option is provided even though in most
cases it is useless. However, if the account is set to have signers below the threshold,
and a contract path has the effect of decreasing the threshold, perhaps it is desired to
then ignore the timeout.
This design covers the various use cases discussed for timeouts.
For example, in a ratchet account for starlight channels, you Bump Sequence and then add a relative timeout of the desired period. This gives the counterparty sufficient time to come online to counterclaim. The relative timeout removes the need to periodically sign update transactions. This improves the security and simplicity of channel implementations.
Strictly speaking, for this use case we minimally need the relative timeout
version of only one time field (ledger sequence or time), and do not need the
other flags except for NO_AUTOREMOVE
. NO_AUTOREMOVE
is useful for keeping
signer reserves reserved until the end of the protocol.
If allowed to be set though, the other options allow for a more flexible model for contracting with timeouts between when certain operations may take place. BUMPSEQ is exempted by default if the account should be restricted for outside operations, given that it's standard use is for timeout based protocols.
The complexity around the swapping of the original_
and actual_
values
allows for a contract designer to have a time invariant identifier for identical
relative timeouts added at different times. Without this, removing timeouts
could only be done by transactions which are signed after observing the relative
times computed.
The signer is 32 bytes so should be compatible.
Old software must be able to understand when an account is locked.
Technically, this change is equivalent to removing keys from an account from the perspective of another account.
None yet.