Proposal: feeSource and feeMultipler

46 views
Skip to first unread message

David Mazieres

unread,
Jan 28, 2019, 3:38:06 AM1/28/19
to Stellar Developers
There are two serious annoyances about fees in the Stellar protocol
right now. First, you have to decide a fee when you sign a transaction,
which makes a lot of protocols not robust to fee increases or network
congestion. Second, and more subtle, the fee has to come from the same
account as the sequence number. While only mildly annoying thus far,
the second point actually becomes a lot worse once we add deterministic
accounts, because now the name of the account has to be tied to whoever
paid the fee.

Viewed this way, I believe we can fix these problems directly with two
simple new mechanisms.

First, we allow a transaction to use a separate account to pay
transaction fees. We do this by changing sourceAccount into a union,
where version 0 is binary compatible with existing account IDs (by just
including the uint256 of an ed25519 key), and the new version 1 has two
fields:

AccountID mainSource; // sequence and default for all other sources

AccountID *feeSource; // if non-NULL, account that pays fee
// also if non-NULL charge 1 more base fee

Now we can have multiple versions of a transaction that are identical
except that they use different accounts to pay the fees. Under my
proposed datacct CAP draft, this means two different people could have
the option of paying the fee to create the same deterministic account.

Second, to eliminate the problem of pre-signed transactions getting
stuck with insufficient fees, as well as the problem of transactions
getting stuck in the "mempool" (i.e., the problem that Stellar has no
equivalent of replace-by-fee and fee auctions will make replace-by-fee
hard to implement), we give each account a new field called
feeMultiplier. The feeMultiplier does exactly what it sounds
like--defaults to 1 but when changed gets multiplied by the fee field in
each transaction to produce the effective fee (or maximum fee if/when we
go to dutch auctions).

Now the fee fields in individual transactions can reflect the relative
importance of the transactions, while the feeMultiplier indicates an
account's overall desire for its transactions to take precedence in
periods of congestion. The benefit here is that the feeMultipler can be
changed independent of any pre-signed or pre-authorized transactions.
Changing feeMultiplier should require medium threshold.

I believe the preceding two mechanisms are sufficient to solve a bunch
of annoying problems with implementing payment protocols on Stellar.
They do require potentially checking two accounts during transaction
validation, but charging an extra base fee somewhat compensates for
that.

While we are at it, I would like to solve another annoyance: having low
threshold signing power on an account is sufficient to drain the account
of all lumens by issuing transactions with ridiculously high fees. I'd
like to propose adding another account flag, FEE_MEDIUM, whose effect is
to require medium threshold to charge fees against the account. Medium
threshold for fees makes more sense now that you don't have to charge
fees to an account to consume its sequence numbers. Setting this flag
could be part of the new operation that sets the feeMultiplier field.
We don't have to do this for the other two to be useful, it just seems
like something nice that we can piggyback onto the proposal at
relatively low cost. It could even be implicit (feeMultiplier of 0 is
multiplier 1 with low threshold, anything else if medium threshold).

Reactions? Suggestions? If people are open to these ideas, I can draft
a CAP with specific XDR changes.

David

Nicolas Barry

unread,
Jan 29, 2019, 3:12:50 PM1/29/19
to David Mazieres expires 2019-04-28 PDT, Stellar Developers
(btw your email address is flagged as SPAM by Google)

Thanks for looking into this.

The new "sourceFeeAccount" is not super satisfying when it comes to use cases - I am not sure which class of problems it's really solving.
Also, does that mean that in a n-party protocol we now need "n" versions of each pre-signed transaction?

Fee multiplier seems like an interesting idea, I just don't know if, in general, it's something that would work for pre-signed transactions as it would require signing a new transaction for the account used for fees; also it may cause interesting problems when reducing its value.
The special fee reservoir from CAP10 doesn't have those limitations as anyone can add to it.

Lastly, if those two features don't make sense in isolation, maybe it's the sign that they should not exist independently (and should be combined somehow).
The idea of fixing pre-signed transactions across transaction boundaries (across ledgers even) that the multiplier implies, probably opens up the door to new solutions. Like a version of CAP10/CAP15 where we can have an operation that allows to create a ledger entry that is a (txHash, amount, expiration) type of thing, that would pay for a future transaction with a given hash (I think you had this kind of use case for testaments in some different write up). The amount would be both credited to the source account and added to the fee bid when the transaction gets processed.

Nicolas






--
You received this message because you are subscribed to the Google Groups "Stellar Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to stellar-dev...@googlegroups.com.
To post to this group, send email to stell...@googlegroups.com.
Visit this group at https://groups.google.com/group/stellar-dev.
To view this discussion on the web visit https://groups.google.com/d/msgid/stellar-dev/87munlyy6s.fsf%40ta.scs.stanford.edu.
For more options, visit https://groups.google.com/d/optout.

David Mazieres

unread,
Jan 29, 2019, 4:53:51 PM1/29/19
to Nicolas Barry, Stellar Developers
'Nicolas Barry' via Stellar Developers <stell...@googlegroups.com>
writes:

> (btw your email address is flagged as SPAM by Google)
>
> Thanks for looking into this.
>
> The new "sourceFeeAccount" is not super satisfying when it comes to use
> cases - I am not sure which class of problems it's really solving.
> Also, does that mean that in a n-party protocol we now need "n" versions of
> each pre-signed transaction?

You don't need n versions, but you have the option of having n versions,
which in some cases is necessary. Coupling the fee to our replay
protection mechanism is a big limitation, particularly as we introduce
features such as deterministic accounts.

> Fee multiplier seems like an interesting idea, I just don't know if, in
> general, it's something that would work for pre-signed transactions as it
> would require signing a new transaction for the account used for fees; also
> it may cause interesting problems when reducing its value.
> The special fee reservoir from CAP10 doesn't have those limitations as
> anyone can add to it.

Can you explain what limitations you are referring to? The assumption
here is that fee accounts have fewer signers than escrow accounts--like
maybe a single signer--so signing a new transaction on a fee account
shouldn't be a big deal.

Why would it be a problem to reduce the feeMultipler? The whole point
of the multiplier is that it isn't part of the transaction.
Conceptually, this covers exactly what users want to express, namely how
important it is for them to execute transactions during congestion.

> Lastly, if those two features don't make sense in isolation, maybe it's the
> sign that they should not exist independently (and should be combined
> somehow).

They definitely make sense in isolation. If you consider the
relationship of feeSource, feeMultipler, and CAP-0005:

* feeMultipler is sufficient to make pre-signed and pre-auth
transactions robust.

* CAP-0005 makes feeMultipler more convenient, because you don't need to
adjust it as aggressively. On its own, it allows pre-auth
transactions using an idiom that you include the maximum possible fee
and just issue your transactions on a dedicated account with a balance
less than the fee.

* feeAccount reduces the number of accounts you need to create for
payment channels, and also makes construction of protocols
significantly less error-prone. In conjunction with CAP-0005, makes
the maximum-fee idiom a lot more convenient. feeAccount offers even
more benefits if/when we add deterministic accounts, because now
multiple accounts can potentially pay the fee to create a
deterministic account.

> The idea of fixing pre-signed transactions across transaction boundaries
> (across ledgers even) that the multiplier implies, probably opens up the
> door to new solutions. Like a version of CAP10/CAP15 where we can have an
> operation that allows to create a ledger entry that is a (txHash, amount,
> expiration) type of thing, that would pay for a future transaction with a
> given hash (I think you had this kind of use case for testaments in some
> different write up). The amount would be both credited to the source
> account and added to the fee bid when the transaction gets processed.

Something like this might work, too. I guess the question is whether we
want to continue taking an account-centric protocols, where accounts
represent balances, replay, sources of fees, and authentication
information, or break it out into separate abstractions for all of
these. A disaggregated design could have separate abstractions for all
of these: trust lines, replay counters, fees paid into particular replay
counters, and principals (signersets).

David

Orbit Lens

unread,
Jan 31, 2019, 8:39:59 AM1/31/19
to Stellar Developers

David's proposal on "feeSource and feeMultipler" made me rethink the whole approach of applying fees in CAP-15. The main reason why we need CAP10/15 is that the fee is a part of the transaction itself, and it's impossible to update fee, as tx signatures automatically become invalid. But what if we could move the bump fee instruction to the tx envelope level?


struct TransactionEnvelope
{
    Transaction tx;
    DecoratedSignature signatures<20>;

    union switch (int v)
    {
    case 0:
        void;
    case 1:
        struct
        { 
           // Account ID to charge fees
	    AccountID replaceFeeSourceAccount;
           // the max fee the replaceFeeSourceAccount will pay
            uint32 replaceFee;
            // signatures from replaceFeeSourceAccount signers
            DecoratedSignature replaceFeeSignatures<20>;
       
            union switch (int v)
            {
                case 0:
                    void;
            } ext;
        } v1;
    }
    ext;
};


The signers of replaceFeeSourceAccount sign a structure containing

  • transaction hash
  • replaceFee value
  • replaceFeeSourceAccount itself.

This approach is better than original CAP-15 as it eliminates the need to create and submit one more "bump-fee" transaction. Any user can update the original TransactionEnvelope and submit it without modifying the transaction itself and its signatures. If the transaction stuck as a result of the insufficient fee specified on the transaction level or fee auction surge, it can be easily re-submitted by a user herself or some third-party service.


Comparing to the CAP-10 and latest David's proposal, managing fees on TransactionEnvelope level rather than account level gives more flexibility and does not require additional account fields or separate entities.


The proposed approach doesn't require cardinal SDK changes. It appears to me like the simplest and extendable solution.


Drawbacks

The replace fee envelopes will contain up to 2x signatures and may require loading one more account (replaceFeeSourceAccount), but comparing to CAP-15 it is more lightweight and potentially easier to implement.

Reply all
Reply to author
Forward
0 new messages