Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIMD-0016: Program Rebatable Account Write Fees #16

Conversation

godmodegalactus
Copy link
Contributor

SIMD for what was discussed solana-labs/solana#21883
A POC is also implemented for the same link at the end of the document.

@t-nelson
Copy link
Contributor

can we get lines wrapped at ~80char here to ease review?

@godmodegalactus
Copy link
Contributor Author

can we get lines wrapped at ~80char here to ease review?

Done

@eugene-chen
Copy link

Eugene from Ellipsis Labs here. I have some reservations about this proposal.

It seems like there are two orthogonal goals here:

  • Create a market for the scarce resource of contested blockspace (e.g. the SOL/USDC Openbook state)
  • Return the accrued revenue to program operators

However, as written, this trades off:

  • Ability for programs to operate autonomously. Each program with contested state will need to have an admin continuously update its write-lock fee and (optionally) maintain its distribution. It seems quite difficult to do all of this completely on-chain, effectively requiring a crank for every hot piece of state.
  • Complexity in fee economics. Jito bundles have tips, tx senders pay base fee and priority fee, and tx senders will additionally pay this state-based write-lock fee that does not go to validators. Reasoning about alignment between validator incentives, trader incentives, and program incentives is very difficult in such a complex system.

An automated mechanism similar to multidimensional EIP-1559 may make more sense. https://ethresear.ch/t/multidimensional-eip-1559/11651

  • Automatic fee escalation and de-escalation removes the need for centralized fee setters, so programs can be truly immutable and uncensorable.
  • Distribute these state-based fees back to the network (some combination of burn and leader), rather than to the protocol. This ensures validators building the most valuable block are aligned with the rest of the network. It also drives value accrual to the token.

@aeyakovenko
Copy link

@eugene-chen can't the automation be built up first as a library in a program that sets these fees, then enshrined if everyone agrees that its the best?

@eugene-chen
Copy link

eugene-chen commented Jan 31, 2023

It does seem better to replace local cranks with a global crank, but still not ideal. An implementation seems quite involved. Such a program would need access to per-state fees from previous blocks for each piece of state, no?

@aeyakovenko
Copy link

aeyakovenko commented Jan 31, 2023

@eugene-chen I don't think it needs a crank. can be done on access. It might need stats about CUs in the last few blocks which are available to the state machine.

@aeyakovenko
Copy link

aeyakovenko commented Feb 1, 2023

@eugene-chen The problem with multidimensional EIP, is that state is unbounded in number of dimensions, any account can be congested. So the amount of state that would be need to be stored and tracked by the runtime automatically is huge. We need applications to enable and pay for this anyways. Iterating at the program level is much faster than in the L1. What's important is that eventually the system can provide enough information to the application program to implement its own multidimensional 1559. Once that works, either it becomes enshrined as a library in the sdk, or maybe it's worth just adding it to sealevel. But probably a library will be good enough.

@eugene-chen
Copy link

Agreed that an iterative approach at the application level, to the extent possible, makes a lot more sense than iterating on the L1.

But requiring programs to actively update fees to be usable, even if temporary, effectively makes it impossible for protocols to decentralize.

Additionally, returning these fees to the program is not particularly incentive-compatible for validators.

@mschneider
Copy link

mschneider commented Feb 2, 2023 via email

@eugene-chen
Copy link

eugene-chen commented Feb 2, 2023 via email

@mschneider
Copy link

mschneider commented Feb 2, 2023 via email

@eugene-chen
Copy link

eugene-chen commented Feb 2, 2023 via email

@mschneider
Copy link

Please add comments in the document, if you have specific questions to the mechanism presented.

@godmodegalactus
Copy link
Contributor Author

I have updated the POC implementation by modification of the account structure itself.

To roll out application fees easily and to avoid misuse of application fees I am thinking of adding a new instruction :
EnableApplicationFees(limit: u64)
The application fees wont be charged if this instruction is not included and the transaction will return an error "Must include EnableApplicationFees instruction to write lock this account".

Let me know your thoughts.

Copy link
Contributor

@t-nelson t-nelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please reformat to fit the template

this doesn't seem precisely enough defined that someone could take it and implement it from scratch, which leads me to believe that the proposal is biased by, or at least intends to lean heavily on, the PoC.

ideally there would be zero code before a proposal is accepted to prevent this kind of thing. at most mocked data structures or pseudo code to clarify difficult to describe logic.

further, there's little elaboration of the required runtime changes, which are by far the part that needs to be most thoroughly understood before any consideration for acceptance. the new program isn't described in particular detail either, eg. no idea what the PDA will hold, what units fees are defined in, etc.

i don't think i can form an opinion as is

proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
proposals/0016-simd-application-fees.md Outdated Show resolved Hide resolved
@godmodegalactus
Copy link
Contributor Author

please reformat to fit the template

this doesn't seem precisely enough defined that someone could take it and implement it from scratch, which leads me to believe that the proposal is biased by, or at least intends to lean heavily on, the PoC.

ideally there would be zero code before a proposal is accepted to prevent this kind of thing. at most mocked data structures or pseudo code to clarify difficult to describe logic.

further, there's little elaboration of the required runtime changes, which are by far the part that needs to be most thoroughly understood before any consideration for acceptance. the new program isn't described in particular detail either, eg. no idea what the PDA will hold, what units fees are defined in, etc.

i don't think i can form an opinion as is

I will rewrite the proposal as you have asked.I have more clear understanding with how things should work.

@ptaffet-jump
Copy link
Contributor

ptaffet-jump commented Feb 10, 2023

Hi, this is Philip from Firedancer.

I'm on board with the premise of the proposal, but the amount of extra state this requires so early in the transaction pipeline scares me a bit, especially if you think about this proposal in the context of a bankless leader. Deciding whether a transaction can successfully pay the fee requires a lookup for each account the transaction uses, which with address lookup tables can be rather large.

Would a simpler solution be adding an infallible transfer built-in program (i.e. the transfer happens even if the transaction fails) where the source is the fee payer and the destination can be application dependent? The DEX can use the instructions sysvar to inspect the transaction and reject the transaction if the infallible transfer isn't to its liking (right destination, sufficient quantity).

It's true that this idea doesn't prevent people from write locking the account just to cause trouble, but anyone write locking the account with a hope of actually making a trade would need to include this instruction. This feels immensely easier to implement and also gives the application tons of flexibility as to what fees it requires, when, and how to rebate them.

@mschneider
Copy link

the issue with this kind of solution is, that it requires for a program to store the relationship between account and write-fee. hence "enabling" application fees now requires some change to the program's account data & it's CPI interface (require new write locked accounts). traditionally changes to account data has been avoided, might be less of an issue now, after the realloc release. changes to CPI interface though are painful to roll out in production.

@godmodegalactus
Copy link
Contributor Author

@t-nelson I have rewritten the proposal with details as required.
@ptaffet-jump Could you check the base fee surcharge section and let us know if it solves the issue.
There is also a new instruction PayApplicationFees.

@tao-stones
Copy link
Contributor

To roll out application fees easily and to avoid misuse of application fees I am thinking of adding a new instruction :
EnableApplicationFees(limit: u64)
The application fees wont be charged if this instruction is not included and the transaction will return an error "Must include EnableApplicationFees instruction to write lock this account".

I like this idea. Something akin to the instruction to request TX prioritization fee, or similar to request TX CU limits. With this, the transaction's ApplicationFee will be know upfront (before accounts are loaded).

On a separate note, due to the similarity this IX has with other IXs (such as requesting compute units, or request prio fee etc. ) One idea mentioned on Discord is to have one general IX that takes a TLV list to set all sorts of limits. The idea is to reduce number of IXs since there is limited space for IXs per TX. wdyt?

@ptaffet-jump
Copy link
Contributor

Here are some responses and thoughts. I'll also add notes on the PR.

the issue with this kind of solution is, that it requires for a program to store the relationship between account and write-fee.

If you didn't want to use a bunch of PDAs, you could have the infallible transfer go to the account they are attempting to write lock. Then you would check they paid the fee happen using the instructions sysvar (which I agree is not ideal). The instructions sysvar isn't one that you can access with ::get, but maybe that could be changed. Don't you still need to change the CPI interface to pass the program ID in order to invoke the Rebate CPI though?


changes to CPI interface though are painful to roll out in production.

I understand the pain, but it feels a little backwards to me to change the runtime to avoid changing the program.


Could you check the base fee surcharge section and let us know if it solves the issue.

I found this section way more complicated than necessary. I think you're calling two different things base fees, right? One is the per-signature fee and the other is a new per-account fee. Then other fees is priority fees, right? I'm concerned this gives validators an incentive to include transactions where the limit is too low, since then they get the extra fee and don't have to do the work of executing the transaction.


I like this idea. Something akin to the instruction to request TX prioritization fee, or similar to request TX CU limits. With this, the transaction's ApplicationFee will be know upfront (before accounts are loaded).

I like this idea too, but it has the same problem with not actually preventing DoS attacks that my infallible transfer idea has. If a transaction specifies a low limit, it may successfully write lock the account and then fail.


One idea mentioned on Discord is to have one general IX that takes a TLV list to set all sorts of limits. The idea is to reduce number of IXs since there is limited space for IXs per TX. wdyt?

I am not in favor of this idea. The instruction limit is 64, which (as far as I know) people don't run into regularly. Normally the constraint people run up against is the transaction size, and this idea won't make much of a difference. The ComputeBudgetProgram only uses 1 byte for a tag, and a TLV will need at least that. So then on every instruction after the first, you save at best 2 bytes (one for specifying the program id to invoke and the other to specify the instruction takes 0 accounts). The extra parsing complexity (and attack surface area) doesn't seem to be worth 2 bytes to me.

## Summary

This SIMD will discuss additional fees called Program Rebatable Account Write
Fees or PRAW Fees. These fees are decided and set by the dapp developer to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fees are decided and set by the dapp developer

how can this offer any protection if left to an attentive, competent dapp developer to deliberately act with good will?

the usability of the chain cannot be left to humans. the protocol MUST drive up fees on the write-contested state. dapp developers can then opt to rebate, in part or whole, for the accounts owned by their program(s). if the protocol can't defend itself against poorly behaving programs/users (by pricing them out!), then its fate is sealed

Copy link
Contributor Author

@godmodegalactus godmodegalactus Jul 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated in the proposal, this proposal is not targeting the congestion control of the whole cluster by itself. This proposal only aims to give dapp authority more control over the usage of the dapp. It is in the dapp programmers/ authority best interest to set this fee correctly do that they make it hard to spam their dapps but not so high that it discourages users to use the dapp. For congestion control there are other fees that are been discussed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not the protocol's job to make dapp users happy. it's the protocol's job to ensure that poorly designed dapps' users are maximally unhappy so that they either a) stop using the dapp, or b) convince the dapps' developers to improve the dapp.

handing this proposal the most valuable, sought after eight bytes in all of the protocol, to only kinda, maybe improve one thing in a very brittle and easy to misuse way would be pretty negligent on the part of protocol maintainers.

Copy link

@mschneider mschneider Jul 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eight bytes to implement program defined account write access control. if it's too much, we might be able to reduce to less if that's more appropriate. we need at least 4 bits though.

collected on the account on which they were set. These fees would be only
applied if the account is write locked by the transaction. The owner of the
account can do lamport transfer to recover these fees. So instead of fees going
to the validator, these fees go to the **dapp developers**. It will be dapp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these fees go to the dapp developers

1) WHAT

how are these incentives in any way productively aligned?

any unrebated fees should be burnt to avoid encouraging dapp developers from using them as a pure profit source. dapp developers bear no burden from having encouraged abusive behavior by their users while causing externalities that likely effect other users. this behavior should be punished, not rewarded.

allowing the dapp devs to retain any fees incentivizes them to design zero-sum races to create state-write competition and justify driving up praw fees.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assure you that driving up the PRAW fees for a dapp is not a good idea. Having high PRAW fees will make the app unattractive for the users. Who will want to trade on dapp which requires 1SOLs of PRAW fees to place an order? Dapp developers always have to find best threshold.

Do you have any concrete examples why do you think dapp developers will like to increase the PRAW fees?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having high PRAW fees will make the app unattractive for the users.

this is 100% the goal. the game design is poor if it's encouraging users to behave abusively either via greedily writelocking or spamming duplicate transactions.

Do you have any concrete examples why do you think dapp developers will like to increase the PRAW fees?

if dapp developers are receiving the fees, they have every reason to maximize that income stream

Copy link

@mschneider mschneider Jul 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong for so many reasons. You argumentation is ad absurdum.

  1. The operating system design is poor when process isolation is not guaranteed, not the application design.
  2. Dapp developers need to provide lowest fees to their target users as they try to maximize value / cost of service. Users are in full control about the fees they agree to when signing a transaction.


Addition of new syscalls to get, set and rebate PRAW fees during program
runtime. Application developers will be able to rebate these fees through the
new syscall, but only if the transaction succeeds, this way transactions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new syscall, but only if the transaction succeeds, this way transactions
but only if the transaction succeeds

i don't really understand the justification for this requirement. ofc the fee-payer must have a sufficient balance for the tx to be eligible for execution, but why does that have anything to do with the eventual result of the transaction?

the feature is being implemented in the runtime, it can side step normal tx execution rules if need be. an example of this is how transactions making use of durable nonces advance the stored recent blockhash so long as the transaction is eligible for execution, regardless of its result. this includes instruction errors, which typically revert all non-fee effects of execution.

the success requirement is going to make it very risky to even attempt a transaction that the user doesn't have high confidence will succeed. that is, the ones this feature is meant to curb. additionally, it harms practical composability as the combinatorial complexity of programs leveraging others makes confidence in the success of a transaction if more difficult to reason about.

it seems far more equitable to honor rebates for all logic that was executed in good will up to failure. this would allow for rebating logic to be implemented in one spot at the end of each instruction, having done relevant accounting during its execution

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine the following transaction,

if (I_am_making_profit) {
      cpi_into_the_dapp_ixA()
} else {
 return Ok(())
}

as a dapp authority I want to punish this kind of spamming. Dapp adds PRAW fees on the accounts so that payer will get rebate only if ixA is called. So spammer can get creative, they create a transaction with two instructions. First instruction will call the ixA and second will do something like this:

I (!i_am_making_profit) {
    return Err(not_making_profit)
}

So spammer will get rebate from the first instructions and in the second he will fail successfully bypassing the PRAW fees.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fine, PRAW fees on accounts owned by w/e program declares ixA get charged. however if that same program had earlier cpi'd into some other program who rebated their PRAW fees for good behavior, those rebates should be honored regardless of the transaction result. that is, program B should not be able to preempt rebates by program A (assuming programs are executed in alphabetical order 😉)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additionally, it harms practical composability as the combinatorial complexity of programs leveraging others makes confidence in the success of a transaction if more difficult to reason about.

The reason why dapp chains are popular is that the developers can actually permission on-chain composability and prevent "noisy neighbors". This proposal is aimed at enabling developers on a shared L1 the same level of access control through an economic incentive. Obviously "it harms practical composability", there is no way to ensure process isolation without restricting the current model. End-user transactions using the reference client should simply never fail, it can be completely avoided.

it seems far more equitable to honor rebates for all logic that was executed in good will up to failure. this would allow for rebating logic to be implemented in one spot at the end of each instruction, having done relevant accounting during its execution

That's an assumption this proposal doesn't make. It should be left to the dapp developer to freely decide when to rebate. Simple ix-level decisions are a special case for infrastructure applications with simple read/write access rules (like pyth). End-user applications often use far more instructions, so a check per instruction is not economical use of CU.

the feature is being implemented in the runtime, it can side step normal tx execution rules if need be.

That's something we actually didn't consider, it's a largely negative change imo though:

  1. it creates harder to reason about semantics for dapp developers. It's way easier to communicate, tx fails -> rebate fails.
  2. it allows for exploiting program errors as free rollbacks after fees have been rebated

those rebates should be honored regardless of the transaction result. that is, program B should not be able to preempt rebates by program A

The signer of the transaction wasted valuable blockspace of program A through his failure to create a successful transaction combining program A and program B. He should reimburse program A roughly the expected profit it could extract from the same amount of blockspace. Program B has the same claim towards the signer from my PoV.

Comment on lines +133 to +134
Once PRAW fees are paid on an account by the payer they are valid for the whole
transaction, even if the same account is write-locked in multiple instructions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this sounds like a footgun. if a program contains both an innocuous instruction, that writes and rebates an account, as well as one that has state competition on that same account, users can just use the former as a NOP to get their rebate before competing on the latter.

charging the fee per-account-reference seems much safer

EDIT: I see this scenario mentioned later in the doc(:tada:), leaving my comment here though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is not clear the writing of the PRAW fees is not taken into account during the transaction. This is important to encourage users to create transactions with more instructions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is not clear the writing of the PRAW fees is not taken into account during the transaction. This is important to encourage users to create transactions with more instructions.

i don't understand this statement at all.

  • what does "writing" mean in this context?
  • why are transactions with more instructions good/relevant?

Comment on lines +144 to +149
some parameters for the transaction. We create a new solana native program
`TransactionHeaderProgram` that decodes the instruction data using a type length
value structure (`TLV`) format and computes the required
`TransactionHeaderParameter`s for the transaction. The `TLV` structure is well
defined for accounts in solana program library repository we will extend the
definition for instruction data. As we have multiple transaction header
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this tvl stuff, while generally a good idea (i proposed it after all 🙃), belongs in a separate SIMD. it's only adding noise in this one. here we can just discuss additions as compute budget program instructions, knowing that they may never actually get implemented there.

i won't be commenting on the tvl-related stuff here as a result

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyways we need to add a way to set PRAW fees. It will be harder to set in compute budget, would be better if it is a part of compute budget instruction. That is why I made it a part of this proposal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be harder to set in compute budget, would be better if it is a part of compute budget instruction.

is there a typo in here? i'm reading it as a self-contradictory statement.

Let Overpaid amount (`O = M - T`)

After execution, we iterate on the rebates issued to calculate total rebated
amount (`R`), For an account there could be multiple rebates during a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For an account there could be multiple rebates

huh? it was stated above that an account is only rebated once

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Program can issue multiple rebates but only the maximum will be taken into account. The rebate will be issued by the runtime only once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds like this section is not sufficiently defined then

Comment on lines 325 to 328
After execution, we iterate on the rebates issued to calculate total rebated
amount (`R`), For an account there could be multiple rebates during a
transaction. Consider that there are `N` rebates on ith account. Each rebate
will be represented as `Rin`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't the syscall just accumulate the rebates in the TransactionContext? then all we do is transfer that amount of lamports back after execution

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thtas the idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not clear from the description

We then transfer `(Pi - Ri) * C` into each writable account and `O + R` back to
the payer.

### Consumption of CUs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these costs should be measured like the rest of the native ops, not extrapolated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok noted, will update these costs accordingly once the changes have been done.


## Backwards Compatibility

This feature does not introduce any breaking changes. The transaction without
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature does not introduce any breaking changes

it breaks consensus. everything the implementation touches in runtime must be feature gated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes agreed, I think it is described.

Comment on lines +552 to +555
If the dapps want to rebate PRAW fees they have to implement very
carefully the logic of rebate. They should be very meticulous before calling
rebate so that a malicious user could not use this feature to bypass
PRAW fees. Dapp developers also have to implement additional
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good that you recognized how brittle this proposal is in practice. we need to fix that. writelock spamming does not come about by demonstration of intelligence by user nor dapp developer.

Copy link

@mschneider mschneider Jul 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the place to discuss any individual's intelligence.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah. this one. apologies this was meant to imply that we're going to get into this situation by greed, not careful thought. i can see how it might be taken as ad hominen if read literally 😅

@ripatel-fd
Copy link
Contributor

This seems like a lot of work for limited gain. This proposal depends on being able to distinguish spam from regular user congestion using on-chain program logic, which is traditionally a losing war. Spamming is usually easier and less risky than defending against such spam, especially when such defenses have to be implemented in on-chain program logic. Worse, these upfront fees introduce additional risk to users of programs, who now have to trust the program that excess fees will be returned. I would therefore recommend against implementing this proposal.

I suggest using a fee mechanism reflects supply (account write/read rate) and demand (spam, user txns) instead. While this may be more expensive to users in the case of spam, it can be assumed that honest users can outprice spammers.

@godmodegalactus
Copy link
Contributor Author

This seems like a lot of work for limited gain. This proposal depends on being able to distinguish spam from regular user congestion using on-chain program logic, which is traditionally a losing war. Spamming is usually easier and less risky than defending against such spam, especially when such defenses have to be implemented in on-chain program logic. Worse, these upfront fees introduce additional risk to users of programs, who now have to trust the program that excess fees will be returned. I would therefore recommend against implementing this proposal.

I suggest using a fee mechanism reflects supply (account write/read rate) and demand (spam, user txns) instead. While this may be more expensive to users in the case of spam, it can be assumed that honest users can outprice spammers.

Is there any technical complexity to implementing this on the firedancer side? Dapp developers can figure out strategies to reduce spamming when given some authority. Dapps can see reduced activity because most of the transactions in the block are errored spams. Currently there is no incentive to write proper bot code, nor to create transactions after reading the state of the cluster. Sufficient PRAW fees will encourage spammers to write more sophisticated code, and read the state of the cluster before making transactions to maximize gains instead of just spamming transactions and losing PRAW fees.
Just because it is "losing war" as you said, does not mean there should be no tools for dapp developers to protect the dapp and its users. The transaction must include the PRAW fees to be paid, so the user knows in worse case how much they will end up paying. Dapps developers can design the tools, ui, and clients to rebate these fees for typical users. Eventually, all the dapps would like to remain competitive in the market, so they would have to find the right balance for PRAW fees to punish spammers and not discourage a typical user.
Writing a congestion control mechanism will make Solana lose its competitive edge of low gas fees cluster. We could end up having similar costs like eth to execute a transaction. It will also punish all the dapp users because of a few spammers. We should have a congestion-controlled fee, but that can be a separate proposal.

@godmodegalactus
Copy link
Contributor Author

@ripatel-fd @t-nelson @ptaffet-jump @jacobcreech

Can we arrange a call to sort it out for this SIMD ?

@mschneider
Copy link

mschneider commented Jul 21, 2023

I suggest using a fee mechanism reflects supply (account write/read rate) and demand (spam, user txns) instead. While this may be more expensive to users in the case of spam, it can be assumed that honest users can outprice spammers.

I don't see, why this is a valid assumption, our experience from observing live usage is exactly opposite.

This proposal depends on being able to distinguish spam from regular user congestion using on-chain program logic

Gross simplification: in cases where distinguishing is complex, a congestion control e.g. local 1559 can be implemented. Application already deploy on-chain program logic for congestion control, this just adds way more powerful arrows to the quiver.

@lheeger-jump
Copy link
Contributor

I don't see, why this is a valid assumption, our experience from observing live usage is exactly opposite.

Do you have some experimental results based on observations from actual spammers?

@t-nelson
Copy link
Contributor

e.g. local 1559 can be implemented

not if praw gets rent_epoch bytes.

i'm generally in agreement with comments from the jump folks here, this is pretty invasive and not solving all that it could be. tack on the self-admitted difficulty of using it correctly and i think we need to keep thinking on this problem

@mschneider
Copy link

I don't see, why this is a valid assumption, our experience from observing live usage is exactly opposite.
Do you have some experimental results based on observations from actual spammers?

Basically every time there is a large amount of liquidations on-chain. Most risk engines with permissionless liquidation endpoints experience this effect. My favorite suspect was a company launching a network of around 20 machines in different data centers to spam failing transactions as fast as possible. Unfortunately I don't have their measurements, but I am sure that no one ends up with such a solution when they don't have reason to justify the expense.

Another example was abas an arbitrage bot many users were running (30+) to capture the spreads between mango v3 & drift v2, which debuted on-chain simulation because rpc level simulation didn't lead to the expected profit margins.

Both deployments were easy to identify and would have been easily kept at bay, without any complex logic on the application side. Simulation of risk free arbitrage with another program as well as a liquidation (write lock of another user's account) are easy to identify and penalize. I don't get where these theories of "impossible cat and mouse game" are coming from. There are very simple solutions that only this SIMD allows that prevent 90% of the issues we have seen.

@mschneider
Copy link

mschneider commented Jul 22, 2023

not if praw gets rent_epoch bytes.

What are you referring to with rent_epoch?

Apart from that I don't understand your argument, what exactly is difficult (for you? for me?)?

and not solving all that it could be.

This is not trying to solve every problem we see with a silver bullet, but it's aimed to precisely address an issue we will always see, no matter how cluster wide contention issues are resolved. A lot of the critique seems to come from the disappointment that it doesn't provide a solution to that problem, but that is not the intention. Different problems need different solutions.

This is not a block building paradigm, this is purely a feature for dapp developers to enforce users to not use stale state to form transaction and split their transactions to be easy to parallelize by the scheduler.

@mschneider
Copy link

I haven't chimed in a while, but I left a lot of comments:

I hope they make clear, that the base layer has the duty to adequately protect the blockspace available to the applications. If it can not create an environment that protects application resources from being denied access momentarily by external parties "just because they can afford higher priority fee". It's simply the equivalent of a corrupt government. Hence account ownership means nothing if the write access to the account can not be governed by the application.

This problem is in discussion now for 12 months, there is no other design currently proposed as a SIMD, I would be very happy to read one, as I just want to get rid of the problem. To me this is an indication that we sussed out all directions and this is actually the only way to solve the problem in reasonable timeframe.

I see a lot of comments from different people on this proposal, that's great and I appreciate most of them. I just want to mention that the clear lack of ownership is frustrating to deal with. In a conversation with Michael Vines on last Friday, and I want to quote him here "we can just merge it" there was 0 appeal to this.

This was in a meeting, that has regularly happened for nearly a year, which @t-nelson never did care to attend albeit being invited. Trent, if you can clear you schedule for a few hours anytime you want, we can run through this with you. If you are so busy, let us be flexible, this would be a great way for us to work towards a solution.

@t-nelson
Copy link
Contributor

What are you referring to with rent_epoch?

these are the soon to be free bytes from AccountInfo that this proposal intends to store the PRAW fee price in (unless i missed a change somewhere). being as the AccountInfo struct is very difficult to change inflight, the concern isn't about 8-bytes so much as the scarcity of account-local storage. allocating them to praw fee price would make them unavailable to (or at least extremely difficult to reclaim) any future use for a broader state-local economic back pressure mechanism.

and not solving all that it could be.

This is not trying to solve every problem we see with a silver bullet...

the state-local scarcity mentioned above is also what motivates my contention here, that we need to make the most use of these bytes possible


i think the broad strokes of this design are good. the mechanics and incentives are what concern me.

  1. requiring an interactive dapp dev to set the price -- humans in the loop will always be slow to respond and frequently make intuitively logical corrections with counterproductive results (see industrial dynamics, jay forrester).

    i think a protocol driven account "heat score", similar to the supply/demand mechanism Richard suggests, from which the fee is then derived, can solve the problem that you've acutely observed and attempt to solve here, as well as more generically address cluster-wide congestion with economic back pressure. unfortunately i'm too smol brained to figure out how to track a per-account heat score in 64bits (how to decay between loads?). not that i believe it is impossible, just a bad math student 😉

    FWIW, i think dapp devs can effectively retain a safer version of this knob via partial rebates

  2. dapp devs collect the fees -- i don't think the motivation for this was ever elaborated?

    it seems to me that this can only provide an incentive toward the development of more abuse-prone games on chain as it is identified as a source of pure profit. a fee is generally justified by the recipient creating value by carrying some burden for the payer, which i'm failing to identify here. the closest analogy i can come up with is along the lines of extortion.

    this concern goes away if non-rebateable PRAW fees are simply burnt by the protocol. burning could also be justified by the fact that the burden of spam is being carried by all cluster participants, so a (miniscule!) deflationary "restitution" would make some sense

these are my main sticking points. i don't believe resolving them is far enough off of this proposal to justify a new one, though i suppose we could go that route. the footguns can likely be resolved by docs and education.

This was in a meeting, that has regularly happened for nearly a year, which @t-nelson never did care to attend albeit being invited.

i don't recall being invited to any such meetings. there was one last week that i was unable to attend, but i was under the impression that its topic was your grant more broadly, of which i have little knowledge of the terms (and did leave some feedback prior with others who were attending). happy to attend any future calls, just please make sure i'm in fact on the invite!

@godmodegalactus
Copy link
Contributor Author

godmodegalactus commented Jul 31, 2023

What are you referring to with rent_epoch?

these are the soon to be free bytes from AccountInfo that this proposal intends to store the PRAW fee price in (unless i missed a change somewhere). being as the AccountInfo struct is very difficult to change inflight, the concern isn't about 8-bytes so much as the scarcity of account-local storage. allocating them to praw fee price would make them unavailable to (or at least extremely difficult to reclaim) any future use for a broader state-local economic back pressure mechanism.

and not solving all that it could be.

This is not trying to solve every problem we see with a silver bullet...

the state-local scarcity mentioned above is also what motivates my contention here, that we need to make the most use of these bytes possible

i think the broad strokes of this design are good. the mechanics and incentives are what concern me.

1. **requiring an interactive dapp dev to set the price** -- humans in the loop will always be slow to respond and frequently make intuitively logical corrections with counterproductive results (see industrial dynamics, jay forrester).
   i think a protocol driven account "heat score", similar to the supply/demand mechanism [Richard suggests](https://github.com/solana-foundation/solana-improvement-documents/pull/16#issuecomment-1638700390), from which the fee is then derived, can solve the problem that you've acutely observed and attempt to solve here, as well as more generically address cluster-wide congestion with economic back pressure. unfortunately i'm too smol brained to figure out how to track a per-account heat score in 64bits (how to decay between loads?). not that i believe it is impossible, just a bad math student wink
   FWIW, i think dapp devs can effectively retain a safer version of this knob via partial rebates

2. **dapp devs collect the fees** -- i don't think the motivation for this was ever elaborated?
   it seems to me that this can only provide an incentive toward the development of _more_ abuse-prone games on chain as it is identified as a source of pure profit. a fee is generally justified by the recipient creating value by carrying some burden for the payer, which i'm failing to identify here. the closest analogy i can come up with is along the lines of extortion.
   this concern goes away if non-rebateable PRAW fees are simply burnt by the protocol. burning could also be justified by the fact that the burden of spam is being carried by all cluster participants, so a (miniscule!) deflationary "restitution" would make some sense

these are my main sticking points. i don't believe resolving them is far enough off of this proposal to justify a new one, though i suppose we could go that route. the footguns can likely be resolved by docs and education.

This was in a meeting, that has regularly happened for nearly a year, which @t-nelson never did care to attend albeit being invited.

i don't recall being invited to any such meetings. there was one last week that i was unable to attend, but i was under the impression that its topic was your grant more broadly, of which i have little knowledge of the terms (and did leave some feedback prior with others who were attending). happy to attend any future calls, just please make sure i'm in fact on the invite!

After thinking over weekend, I have the following conclusions and points of disagreement that should be resolved:

  1. Where should fees go?
    • Burn: Burning fees will give validators more incentive to order transactions in such a way that they fail. Burning fees will reduce SOL supply and make SOL more expensive. The authority of the account could burn sol if there is a bug in setting the PRAW fees mechanism. This feature could also become a way to burn SOLs which is not the purpose of the SIMD.
    • Fees go to account authority: Dapps could create a way to extort the users, which can be argued that it could already be done without the necessity of PRAW fees. This feature does not add any new security concerns. More of a philosophical question about why the account authority should receive the fees. I argue because they are the authority of the account, so they should have a say on how to enforce the account's usage.
  2. Updating the Account structure?
    • Currently, account structure is the core structure and is very hard to modify. In our POC we were able to modify the structure without making it incompatible with the previous implementation, but a versioning of this structure is the right way forward. So I have created the issue which will address this issue :
      Add versioning to Account struct solana-labs/solana#32665
  3. Who should set the fees?
    • Authority: SIMD argues that the PRAW fee should be set by account authority to efficiently have more control over the account. The feature is not to do congestion management but to discourage spamming. So dapps should have full control over setting the fees. The argument against is that developers are slow to react.
    • Cluster: EIP-1559 could be the way to do some congestion control. It could be part of PRAW fees where PRAW fees are partly burned, and the program could rebate the other portion. Creating a mechanism like this is a whole proposal and not a simple way to wrap your head around it. There had been a long discussion going in the economics channel about it. For this proposal, this kind of mechanism will make things worse for dapps, because using high-traffic dapps will be more expensive. And proposal does not aim to reduce valuable traffic on dapps but punish spamming activity.
  4. CPI problems
    The spamming issue partly stems from no control over who can CPI into a contract. This way, spammer are not incentivized to read the cluster state but blindly spam specialized contracts that will do the work for them. Dapps have no control over the way their contracts and accounts are used.
  5. Failing Transactions:
    I think we all agree that another problem is failing transactions. The failing transactions use up blockspace without bringing anything positive to the cluster. Currently, there is no punishment for sending a transaction that fails. Usually, preflight checks help normal users ensure that their transaction is valid by simulating them, but spammers can skip this check. This SIMD wishes to penalize even the failing transaction, but this creates a new way of handling failed transactions which vastly differs from other chains philosophically.
  6. Writelocking accounts without using them:
    Write-locking and account and writing into it or not using it at all should also be punishable somehow.

This SIMD highlights the difference of opinion between L1 and dapp developers. It is hard to change L1 without providing any concrete solution that resolves most of the issue, and dapp developers cannot enforce how their dapps are used. So in summary, SIMD-16 solved many issues but fails to get consensus over some philosophical questions and one technical issue about changing the account structure.
We will continue implementing solana-labs/solana#32665 to solve the technical issue and continue brainstorming on the current proposal or eventually create new proposals to addresses each problem.

@mvines mvines changed the title Program Rebatable Account Write Fees SIMD-0016: Program Rebatable Account Write Fees Aug 13, 2023
@jacobcreech jacobcreech added standard SIMD in the Standard category core Standard SIMD with type Core labels Aug 16, 2023
godmodegalactus and others added 2 commits October 15, 2023 16:03
…count_fees_changes_oct_2023

Changes to remove rebates syscall and update the motivation
@godmodegalactus
Copy link
Contributor Author

Updated the proposal to make motivation more clear.
Remove a rebate syscall.
Added a concrete example.

@nicovrg
Copy link

nicovrg commented Dec 1, 2023

whats currently blocking this going through?

@metaproph3t

This comment was marked as off-topic.

@0bMelody
Copy link

whats currently blocking this going through?

A few things

  • Alternative solutions were proposed to the problems described that I and many others deem less detrimental to the protocol
  • The broader economics community has recognized a need to revisit the basics of economics instead of making such superfluous changed to the protocol.

I too am strongly against this proposal.

@lheeger-jump
Copy link
Contributor

lheeger-jump commented Apr 14, 2024

This proposal has been stagnant for 4 months without a clear direction for its future. I believe this proposal, although its technical formulation is largely sufficient for acceptance, it introduces many questions and many issues. Certainly many more than it addresses:

  1. Why should app developers retain any rights to the transaction fees of the chain?
  2. Does this result in the practical effect of reducing spam?
  3. What do transaction fees represent? Put another way, what are transaction fees actually representative of?
  4. What is the likelihood of adoption? Do app devs actually care about spam on the network?
  5. Is the added runtime complexity of adding PRAW worth it?

The best engineering/economic solutions have answers to questions like these, or can at least defend against the alternatives. Every one of these questions has had a pretty nasty counterpoint that other simpler, tried solutions do not suffer from.

For these reasons, I plan to move this PR into a stagnant state soon.

@godmodegalactus
Copy link
Contributor Author

This proposal has been stagnant for 4 months without a clear direction for its future. I believe this proposal, although its technical formulation is largely sufficient for acceptance, it introduces many questions and many issues. Certainly many more than it addresses:

1. Why should app developers retain any rights to the transaction fees of the chain?

2. Does this result in the practical effect of reducing spam?

3. What do transaction fees represent? Put another way, what are transaction fees are the fees actually representative of?

4. What is the likelihood of adoption? Do app devs actually care about spam on the network?

5. Is the added runtime complexity of adding PRAW worth it?

The best engineering/economic solutions have answers to questions like these, or can at least defend against the alternatives. Every one of these questions has had a pretty nasty counterpoint that other simpler, tried solutions do not suffer from.

For these reasons, I plan to move this PR into a stagnant state soon.

This proposal is widely loved by many while equally hated by many. Technically it will reuse rent epoch space to save the required information with little to nothing performance impact.

Question 1. Is a philosophical question while the arguments why the dApp should receive the fees has been explained in the proposal, there are also a few reasons not to do so.

Question 2. Theoretically reduces spam but testing its effect is hard to predict unless it lands the mainnet.

Question 3. Frankly did not understand the 3rd question.

Question 4. We have been approached by many protocols showed us their support and who were ready to adopt, but it would have required additional development on their side.

Question 5. I have been wondering of this question for a long time.

In any case I agree to move this proposal to a stagnant state soon. I can revive the proposal whenever I have more support from the community.

@lheeger-jump
Copy link
Contributor

I am marking this SIMD as stagnant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Standard SIMD with type Core stagnant standard SIMD in the Standard category
Projects
None yet
Development

Successfully merging this pull request may close these issues.