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-0082: Relax Transaction Constraints #82

Closed

Conversation

apfitzge
Copy link
Contributor

@apfitzge apfitzge commented Nov 2, 2023

The first in a series of SIMDs aimed at the relaxation of constraints blocking us from (potentially) having asynchronous execution.
This proposal does not lock Solana into moving towards asynchronous execution.
This proposal stands on its own to simplify the protocol and give more flexibility in implementation of both block-production and block-validation.

@apfitzge apfitzge force-pushed the relax-transaction-constraints branch from 820aecc to 819d63a Compare November 2, 2023 04:15
@apfitzge apfitzge changed the title SIMD-XXXX: Relax Transaction Constraints SIMD-0082: Relax Transaction Constraints Nov 2, 2023
Comment on lines 66 to 84
3. Have program accounts that:
1. exist
2. are executable
4. Have writable accounts that are:
1. not executable, unless owned by
`BPFLoaderUpgradeab1e11111111111111111111111`
2. if owned by `BPFLoaderUpgradeab1e11111111111111111111111`,
then `BPFLoaderUpgradeab1e11111111111111111111111` must be included
3. if owned by `Stake11111111111111111111111111111111111111`, then the
current slot must not be within the epoch stakes reward distribution period
5. Have executable `BPFLoaderUpgradeab1e11111111111111111111111` owned accounts
with `UpgradeableLoaderState::Program` state, and derived program data account
that exist
6. Have a call chain depth of 5 or less
7. Have no builtin loader ownership chains
(pending `4UDcAfQ6EcA6bdcadkeHpkarkhZGJ7Bpq7wTAiRMjkoi`)
8. Have total loaded data size which does not exceed
requested_loaded_accounts_data_size_limit
(pending `DdLwVYuvDz26JohmgSbA7mjpJFgX5zP2dkp8qsF2C33V`)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tried to be as specific as possible in the document itself, but these constraints (3-8) can be summarized as "transaction must be executable"

@apfitzge apfitzge marked this pull request as ready for review November 2, 2023 07:46
Copy link
Contributor

@lheeger-jump lheeger-jump left a comment

Choose a reason for hiding this comment

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

I have done a first pass but will need to go more in depth later.

Specifically, this proposal relaxes constraints that a transaction included in
a block must:

1. Have a fee-payer with enough funds to pay fees
Copy link
Contributor

Choose a reason for hiding this comment

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

This list seems to denote the current status of constraints on transactions. This is useful background, but we need to precisely specify the new constraints on transactions.

Copy link
Contributor

Choose a reason for hiding this comment

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

... in a separate list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bit confused on what you're suggesting would make the document more clear here; this proposal does not add any new constraints.
The list here is an incomplete list of the constraints on transactions, it is only the constraints that are being removed/relaxed.

Copy link
Contributor

Choose a reason for hiding this comment

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

The list describes what the constraints are now, but does not explicitly list what the relaxed constraints are. Consider that I or another FD dev needs to stare at this and implement the exact rules for what defines a valid transaction.


## Detailed Design

Specifically, this proposal relaxes constraints that a transaction included in
Copy link
Contributor

Choose a reason for hiding this comment

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

This list seems to mix "constraints on transactions which invalidate entries and blocks" and "constraints on transaction execution which invalidate the transaction". The list should be split up or the ones of the latter type should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a very fair comment, as that is something is changing with this proposal. Currently, the list of constraints that invalidate the block is a superset of those which invalidate execution. That will no longer be the case, and I should make that more clear.

Comment on lines 80 to 83
7. Have no builtin loader ownership chains
(pending `4UDcAfQ6EcA6bdcadkeHpkarkhZGJ7Bpq7wTAiRMjkoi`)
8. Have total loaded data size which does not exceed
requested_loaded_accounts_data_size_limit
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add links to the feature documents.

block-limits would require the validator to check whether or not a transaction
is executable, which negates the benefits of this proposal.

Additionally, f these transactions did not count towards block-limits, a
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
Additionally, f these transactions did not count towards block-limits, a
Additionally, if these transactions did not count towards block-limits, a


### Block-Limits

Pending the activation of `2ry7ygxiYURULZCrypHhveanvP5tzZ4toRwVp89oCNSj`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a link.

Copy link
Contributor

Choose a reason for hiding this comment

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

SIMD should stand for itself and should not have any links, as far as i know.

Copy link
Contributor

Choose a reason for hiding this comment

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

It at least needs to describe the feature.

Comment on lines 129 to 132
validators must validate a block is within block-limits.
With this proposal, some transactions may not be executable, but will still
count towards block-limits.
If these transactions did not count towards block-limits, the validation of
Copy link
Contributor

Choose a reason for hiding this comment

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

How do they specifically contribute to block limits.

effect on state.
In case 2, the fee-paying account should be drained of all funds, but have no
other effect on state.
In case 3, the fee-paying account should be drained of all funds, with 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 seems a bit harsh, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Potentially this is too harsh. Alternatively we could just drain them to the rent-exempt level.
Not sure which seems fairer. If submitting a transaction that cannot pay fees, they should be punished imo.

Choose a reason for hiding this comment

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

Imho, since the commission is paid, the transaction should be executed. Deleting the account is a different event.

Comment on lines 107 to 121
### Fee-Paying

Currently, iff a transaction's fee-payer does not have enough funds to pay the
fee, the transaction cannot be included in a block. With this proposal, it is
possible for such a transaction to be included in the block, and there are
three different edge-cases to consider:

1. The fee-payer account does not exist (0 lamports)
2. The fee-payer account does not have enough funds for the entire fee
3. The fee-payer account has enough funds for the fee, but would no longer be
rent-exempt

In case 1, the transaction should simply be ignored for execution, and have no
effect on state.
In case 2, the fee-paying account should be drained of all funds, but have no
Copy link
Contributor

Choose a reason for hiding this comment

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

probably a good exercise to also enumerate the normal case

In case 2, the fee-paying account should be drained of all funds, but have no
other effect on state.
In case 3, the fee-paying account should be drained of all funds, with fees
being paid to the block-producer, and the remainder of lamports being dropped.
Copy link

Choose a reason for hiding this comment

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

dropped => burnt?

are broken, the entire block is marked invalid; with this proposal, the
block is not marked invalid, but the transaction will not be executed.
These constraints must still be satisfied in order for the transaction to be
executed, and have an effect on state. However, there are some new considerations
Copy link

Choose a reason for hiding this comment

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

maybe better off being explicit about side-effects on some on-chain states for these constraints-violating transactions. namely, the status cache to avoid repeated inclusion of same transactions.

- Removing fee-paying requirement could allow validator clients to produce
blocks that do not pay fees. If not checked by block-producer, this could
allow malicious users to abuse such producers/leaders.

Copy link

Choose a reason for hiding this comment

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

also, malicious leaders could create full of garbage blocks, which only contains bad transactions at no cost, burdening all the validations onto other validators, esp, heavy account state lookup.

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed with @ryoqun, this attack vector is the main thing that needs to be solved. Maybe this specific problem can be discussed in a separate SIMD since relaxing other transaction constraints is more straightforward.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

made a comment in this chain: #82 (comment)

I don't think there's a DOS that's creating more work than would be possible within current protocol.
I can currently create a block thats full of valid heavy transactions, and then tag in some invalidating transaction at the last tick. All the validators wasted their time executing all those txs, and there's no reward for them since the block is thrown out entirely.

This would change the vector, since they could have all txs that do not pay fees. But, that only makes the execution less intense, since they still have a cost that counts towards block limits.

relaxed as well.

The relaxation of these constraints is only relaxed for transactions being
included in a block. During block validation, if any of these constraints
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this affect transaction simulation? Currently, we get an error when we simulate transactions where the payer does not have enough balance. This will make these kinds of errors indetectable during transaction simulation.

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'm not sure what you mean. Transaction simulation is unrelated to block invalidation, and doesn't change with this proposal.
You'd still get the same transaction error which indicates it cannot pay for fees.

3. The fee-payer account has enough funds for the fee, but would no longer be
rent-exempt

In case 1, the transaction should simply be ignored for execution, and have no
Copy link
Contributor

Choose a reason for hiding this comment

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

Should also consider that base fee will eventually change and could be much greater than now.

- Any dynamic fees based on block utilization cannot/should not reward the
block-producer directly. Otherwise, this incentivizes block-producers to fill
blocks with non-fee paying transactions in order to raise fees.
- Non-fee paying transactions included in a block will be recorded in long-term
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be a way to attack the cluster and use more space. A malicious leader could create 48M CU / (CU required to load payer account which currently stands at 0) number of transactions. This could be a massive number of transactions, depending on CUs charge that we decide to load the payer account. If each transaction was given the maximum size of 1280 bytes or eventually more if we include ZK transactions, then I can possibly create a huge block burdening the whole cluster's network resources because of the turbine.

I feel like the leader should be somehow punished/slashed for adding transactions where the payer does not have enough balance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently transactions do have a minimum cost of 1070 CUs = 720 SigVerify + 300 WriteLock.
This corresponds to a maximum of 44776 txs per slot, assuming 48M CU limit.

Additionally, cost has 1 CU per 4 bytes of instruction data. So large ix data txs would cost more than this bare minimum of 1070 CUs as well.
It's still a large number of transactions of 34532 txs per slot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's worth noting that currently, all direct rewards are going to the block-producer anyway.
If that large number of transactions were valid fee-paying transactions, it would only be more work for other validators than if they could not pay fees. Either way, other nodes are not directly rewarded for the validation/execution.

There is still some discussion to be had around indirect rewards via the burning of SOL in those fees. I think that's potentially a valid reason we may want to force the block-producer into paying fees. Hoping to discuss this more

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I agree, block producers should pay a fee as they are using network resources, storage space to transfer invalid transactions. Malicious node can just start creating blocks with invalid transactions of 1280 bytes using 44.20096 MBs/ block in network and storage.

- Transactions that would previously be dropped with an error, can now be
included, and even charged fees.
- Users must be more careful when constructing transactions to ensure they
are executable if they don't want to waste fees
Copy link
Contributor

Choose a reason for hiding this comment

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

are there additional tools (or simulator enhancement) needed for transaction submitters ensure their transactions against those relaxed constraints?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Simulation doesn't change. It currently would tell you that your transaction had an error. That error doesn't change, it only changes what will happen to a block it may be included in.

For example, if a transaction had an invalid program account, simulation will still return ProgramAccountNotFound error.
If the user simulates, and then still submits that transaction, then they probably deserve to be charged, imo.

updates. This is because the only account-state required for transaction
validation is the ALT resolution, which is resolved at the beginning of a slot.
- Block-production could be done asynchronously
- Block-validation could be done without execution, but still relies on the
Copy link
Contributor

Choose a reason for hiding this comment

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

could be done without execution

Can use some explanations/examples here.

- Block-validation could be done without execution, but still relies on the
execution of previous blocks.

## Security Considerations
Copy link
Contributor

Choose a reason for hiding this comment

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

Could any other relaxed constraints, in addition to relaxing "fee-payer requirement", lead to similar dos vector, if block producer build with bad transactions?

Is it necessary to charge transactions failed due to those relaxed constraints by its transaction base fee?


- Any dynamic fees based on block utilization cannot/should not reward the
block-producer directly. Otherwise, this incentivizes block-producers to fill
blocks with non-fee paying transactions in order to raise fees.
Copy link
Contributor

Choose a reason for hiding this comment

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

imo, it is necessary to have someone to pay for ledger space occupied by those failed transactions (that do not update global state machine). There are several ideas, including have Producer pay. Should the discussion of how to do that be part of this SIMD?

## Drawbacks

- Any dynamic fees based on block utilization cannot/should not reward the
block-producer directly. Otherwise, this incentivizes block-producers to fill
Copy link
Contributor

Choose a reason for hiding this comment

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

Any dynamic fees based on block utilization cannot/should not reward the block-producer directly

Humbly not like the sound of a future proposal (eg Dynamic base fee) is already constrained by current design.

But if bock producer cannot include no-paying transactions for free, say producers are liable for adding those bad transactions to block and have to pay for those, then we wouldn't have to worry about this drawback?

In case 1, the transaction should simply be ignored for execution, and have no
effect on state.
In case 2, the fee-paying account should be drained of all funds, but have no
other effect on state.
Copy link
Contributor

Choose a reason for hiding this comment

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

With this, Case 2 would never exists, would bad actors fall back to case 1 to quickly build tx with random payer account for DoS attack.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With this,

Might have missed a comment this is attached to. With what?

Case 2 would probably not occur if it was a malicious actor, but could happen if some non-strict block-producer made and assumption a fee-payer was good and was not.

account state necessarily requires synchronous execution within the protocol.
This proposal on its' own, will not enable asynchronous execution, but it will
remove one of the barriers to asynchronous execution.

Copy link
Contributor

Choose a reason for hiding this comment

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

A bit confused by "aim" in Summary section and Motivations here. As "aim" seems to yield benefit to block producer ("...transaction can be included..."), which is not part of protocol; while Motivation talks about modifying protocol.

Is it correct yo say this proposal has two parts:

  1. remove listed constraints/requirement of transaction for block producer to include them into block; this part solely in Producer implementation, does not modify protocol;
  2. instead of invalidate entire block at earlist failure of transaction due to named constraints, validator only not execute bad transactions but will continue validate the block. (bad transactions included in ledger). This part of protocol altering.

or maybe I am thinking on wrong track?

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 think only your 2nd point is included in the proposal. Block-production changse are enabled by the changes in the proposal, but not required beyond potential changes to the fee-colection.

instead of invalidate entire block at earlist failure of transaction due to named constraints, validator only not execute bad transactions but will continue validate the block. (bad transactions included in ledger).

yes. Those bad transactions may end up having limited effect if we are still able to collect fees, or if we decide to make the block-producer cover those fees. They will not be executed though.


Proposal does not suggest or require the block-producer to make any changes, but allows for changes. For several of the constraints, the producer is still incentivized to perform the checks (fee-payer, nonce) because otherwise they will not receive rewards for those transactions. There's freedom in how that is done, and the block-producer could potentially do this in a non-strict fashion.

I'll cover this in the updated prop, but essentially block-validation and consensus really consists of 2 primary questions:

  1. is this block valid?
  2. what is the result of the block?

The changes here are intending to make answering this first question, "is this block valid?", a simpler process that does not require executing the block. This proposal separates these questions logically, but w/ current voting we still require the 2nd question, "what is the result of the block?", be answered synchronously.


## Summary

This proposal aims to relax some of the constraints on which individual
Copy link
Contributor

Choose a reason for hiding this comment

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

to relax some of the constraints

to clarify, "relax" means "removal"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The constraints still exist in the sense we need to check "can this transaction be executed". They do not exist for the validity of the block.

Right now, those 2 different types of constraints are overlapping. I need to re-write this proposal with @lheeger-jump's suggestion on making it very explicit that these 2 things are different.

count towards block-limits.
If these transactions did not count towards block-limits, the validation of
block-limits would require the validator to check whether or not a transaction
is executable, which negates the benefits 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.

I think the case here is "producer builds a block of 48M cu, but validator only spent less than 48M to execute all transactions (as some of TXs are failed and not executed)", and this should be OK (except the DoS vector - that entire block is unexecutable txs, which can be addressed by making producer pay for these unexecutable txs)

Comment on lines 142 to 143
- Transactions that would previously be dropped with an error, can now be
included, and even charged fees.
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
- Transactions that would previously be dropped with an error, can now be
included, and even charged fees.
- Transactions that would previously be dropped with an error without paying fees, can now be
included and will be charged fees.

I think "and even charged fees" doesn't sound declarative enough. My understanding is that the crux of this SIMD is that before we dropped txs for a variety of reasons and didn't charge fees and after we will allow invalid txs to be in a block and will charge fees for them.

Comment on lines 43 to 47
2. Relax all but fee-paying constraint
- This was actually the initial proposal, but it was decided that it would
be better to relax as many constraints as possible, rather than just some.
Any reliance on account state, means the protocol requires synchronous
execution.
Copy link
Contributor

Choose a reason for hiding this comment

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

To clarify, "it would be better to relax as many constraints as possible" just means that the fee-paying constraint is also removed right? I think you could say that directly here.

Comment on lines 49 to 53
- This was considered, since it is a transaction-level constraint that is
depdendent on account-state. However, due to entry-level and block-level
constraints that rely on the address lookup table resolution, this
constraint cannot easily be relaxed without also relaxing those
constraints.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really understand why there is still a constraint for address lookup tables. If the lookup table is invalid for some reason can't validators just charge the fee payer some 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.

ALT resolution contributes to constraints at higher levels i.e. entry and block.

Entries need to have non-conflicting transactions (without adoption of #83).
Blocks are required to not exceed account write limits (currently 12M CUs).

In both these situations, if we allow ALTs to not resolve I think the behavior becomes very unclear. Do we only consider the static accounts? all resolvable accounts? no accounts?
Not clear to me any of those options is ideal or makes sense. I think we'd like to remove this constraint eventually, but I think it probably makes more sense to do after these complicating entry and block constraints are also removed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, thanks for explaining what the entry and block constraints are, I hadn't considered those. FWIW ALTs were designed to be apend only and the warmup time (currently one slot) is configurable by the runtime and can be increased in the future if it helps bankless leaders manage a cache of ALTs. So I think we could try to move forward with removing this constraint.

a block must:

1. Have a fee-payer with enough funds to pay fees
2. Have a valid nonce account, if specified
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you consider that both normal transactions and durable nonce transactions can only be processed once to be valid? Validators and bankless leaders can use the status cache to avoid including normal transactions more than once, but they need to check that the nonce is valid or not to avoid including durable nonce transactions more than 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.

Considered, but I need to rewrite sections of the proposal to be very explicit.

Status cache should still be used to avoid including transactions multiple times. Duplicate inclusion of transactions is still a violation of constraints and leads to the entire block being marked as invalid. This does not depend on account state, which is why I think this should be left in.

With respect to nonces, we want to avoid depdendence on account state, so cannot check the validity of the nonce account for the question of block validity. However, the nonce acount state must still be checked before execution. If the nonce account does not exist or is otherwise invalid, the transaction is not executed and fees are not charged to the fee-payer.
I view this as a similar situation to the fee-payer check; The block-producer is incentivized to check these states. They are free to do that in some non-strict method, but if done incorrectly, they lose out on rewards and the transaction has no/limited on state and have effectively burned their CUs.

There's an ongoing discussion of if fees should be paid by the block-producer should a transaction be unable to pay. So whether or not the producer gets charged fees in these cases is still an open question.

@apfitzge
Copy link
Contributor Author

Pushed some clarifications. As mentioned, I need to re-write a few sections wrt being explicit on separation of "includability" and "executability" constraints.

I think the main open question is how to treat non fee-paying transactions. In my opinion, this should be answered and included as part of this SIMD.

  1. Current proposal allows txs to go entirely unpaid
  2. Could charge the block-producer unpaid fees

I'm not that oppposed to 2, although it might be more complicated. It opens some new questions around what to do if the producer also cannot pay for the fees.

@jstarry
Copy link
Contributor

jstarry commented Nov 15, 2023

I think it's hard to imagine a fee-maximizing validator not maintaining a status cache, durable nonce cache, ALT cache, etc (are there more?). I lean towards enforcing all validators to maintain those caches in order to produce valid blocks. Is that also an option? (EDIT: If we continue forward assuming that validators are incentivized to avoid non-fee paying transactions, can we explain how they could reasonably implement that? I think block space could be DOS'd otherwise)

@jstarry
Copy link
Contributor

jstarry commented Nov 15, 2023

I think the main open question is how to treat non fee-paying transactions

Are these the only cases in which transactions don't pay fees?

  1. Replayed transactions (normal or durable)
  2. Fee payer lacks sufficient funds

Can you document them in the SIMD and explain why they can't be avoided and need to be addressed?

@apfitzge
Copy link
Contributor Author

Are these the only cases in which transactions don't pay fees?

1. Replayed transactions (normal or durable)

2. Fee payer lacks sufficient funds

I'll document it, but to be clear. Normal transactions can still not be replayed. This SIMD does not propose changes to the status cache. If a block contains an already executed normal transaction, then the entire block will be invalid.

With nonced transactions, correct. They could be included multiple times, would not pay fees or be executed after the first one.

I think it's hard to imagine a fee-maximizing validator not maintaining a status cache, durable nonce cache, ALT cache, etc (are there more?). I lean towards enforcing all validators to maintain those caches in order to produce valid blocks. Is that also an option? (EDIT: If we continue forward assuming that validators are incentivized to avoid non-fee paying transactions, can we explain how they could reasonably implement that? I think block space could be DOS'd otherwise)

Just to re-iterate, the SIMD doesn't propose changes to status-cache.

Is that also an option?

Sure, rejecting wholely or part of the SIMD would leave those constraints in the protocol.

validators are incentivized to avoid non-fee paying transactions, can we explain how they could reasonably implement that

There's no reason a validator could not continue to do strict fee-paying checks, as they do today, for block-production.

I think block space could be DOS'd otherwise

Yeah, so this part of prevention is behind a currently inactive feature: solana-labs/solana#29595

That feature will cause transactions to count towards block-limits with the requested CUs (+builtin costs), not actually executed.
WRT this proposal, transactions regardless of if they can pay fees or are executed, will count towards block-limits as if they could.
So I don't think there's any additional worry about block space DOS attacks, these non-fee paying transactions can only be cheaper to execute than if they could pay fees, but count towards block-limits at full cost.

@jstarry
Copy link
Contributor

jstarry commented Nov 17, 2023

Couldn't some malicious actor send a bunch of non-fee paying transactions then to saturate block-limits and prevent fee-paying users from using the chain? I think this should be explicitly prevented by the design of this SIMD if possible.

@apfitzge
Copy link
Contributor Author

Couldn't some malicious actor send a bunch of non-fee paying transactions then to saturate block-limits and prevent fee-paying users from using the chain? I think this should be explicitly prevented by the design of this SIMD if possible.

A malicious user could send those transactions, but any reasonable producer will have some logic, albeit not necessarily strict, for filtering out transactions that cannot pay fees. Since if they pack those transactions they either get no rewards, or have to pay the fees themselves (hoping to discuss this tomorrow at community call).

I will explicitly mention this potential case in the SIMD.

@apfitzge apfitzge marked this pull request as draft November 17, 2023 22:07
@apfitzge
Copy link
Contributor Author

Converting to a draft as I rework the proposal to fit the feedback received during the core community call.

@apfitzge apfitzge marked this pull request as ready for review June 12, 2024 06:19
@apfitzge apfitzge requested review from jstarry and lheeger-jump June 12, 2024 06:19
@apfitzge
Copy link
Contributor Author

@lheeger-jump made the lists much more clear, tried to enumerate all relevant checks that affect whether or not a transaction can be accepted in a block.

Because many of the other changes are less controversial, I've opted to remove the fee-payer relaxation out of this SIMD and would do that as a follow-up proposal.
Acceptance of this SIMD will still require that all transactions can pay fees.

@aeyakovenko
Copy link

@apfitzge @jstarry this math works out

Allow invalid txs and skip over them

  • skip over invalid signature, invalid fee payer, etc...

Subtract the number of invalid txs at the end of the epoch from the leaders reward points (1 vote 1 point, so each invalid tx is 1 missed point)

  • max number of invalid txs is 100k or 100,000 * 0.000005/2 missed burn reward for the network, or 0.25 sol

5800 sol is the min to be scheduled once per each for a 4 slot period. max number of invalid txs in that period is 100k. * 5800 * 0.05 reward apy ~= 2 sol per epoch in rewards

if the validator didn't vote at all, they lost out on 2sol worth of network rewards. If they voted, they lose out on at least 1/4th of the rewards, which is > 0.5 sol.

@apfitzge
Copy link
Contributor Author

TVC eliminates the 1:1 vote-to-credit relationship, so those number would need to be tuned.
Not sure where you are getting 100k as the maximum number of invalid transactions? Malicious leader could pack much more than than in 4 slots.

Even without the complicating factors of relaxing fee-payer or signature constraints, which are contentious changes, this proposal seems to be idling waiting for reviews.
We can have follow-up or even separate SIMDs for those ideas, but it seems adding too many things to any SIMD will slow it down - particularly when those things are contentious.

Maybe I'm off - @jstarry lmk if I should add these back into this proposal.

@aeyakovenko
Copy link

How can proposer exceed the shred limits @apfitzge?

I don't think they can exceed 100k txs in 4 slots, but they can submit super large txs and reduce the penalty. But the penalty can just be tuned to be 10 points per invalid tx, or X points per tx byte. Either way.

TVC changes don't really impact this since the best case is about the same.

- be executable
- the owner account be owned by the native loader: `NativeLoader1111111111111111111111111111111`
- the owner account must be executable

Choose a reason for hiding this comment

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

We need a complete test suite that tests every single one of these constraints (via txn execution) so that we can also test the behavior when the feature flag is flipped to make sure we relax all the correct constraints

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, any client should be testing against the protocol, and those tests much change if the protocol changes.

There should already (big should in our codebase...) be tests for all these cases, as they are currently protocol violations, that we must check for.
Tests can be modified to use feature-flag which would change the result of processing pipeline from rejected -> not executed.

@apfitzge
Copy link
Contributor Author

How can proposer exceed the shred limits @apfitzge?

I don't think they can exceed 100k txs in 4 slots, but they can submit super large txs and reduce the penalty. But the penalty can just be tuned to be 10 points per invalid tx, or X points per tx byte. Either way.

TVC changes don't really impact this since the best case is about the same.

How can proposer exceed the shred limits @apfitzge?

I don't think they can exceed 100k txs in 4 slots, but they can submit super large txs and reduce the penalty. But the penalty can just be tuned to be 10 points per invalid tx, or X points per tx byte. Either way.

TVC changes don't really impact this since the best case is about the same.

because that's not the shred limits, afaik shred limits would be 131072 txs per slot.

proposals/0082-relax-transaction-constraints.md Outdated Show resolved Hide resolved
Comment on lines +169 to +170
3. Transaction signatures must be valid and in the same order as the static
account keys in the `VersionedMessage`.
Copy link
Contributor

Choose a reason for hiding this comment

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

From conversation in #159 we should only be requiring the fee payer signature to be valid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, but that was a separate change not part of this SIMD.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok maybe rather than having a single all encompassing SIMD for transaction constraints, we limit this one to account loading related constraints?

Comment on lines +187 to +194
7. Transactions that use address lookup tables must be resolvable:
- The address lookup table account must exist.
- The address lookup table account must be owned by the address lookup
table program: `AddressLookupTab1e1111111111111111111111111`
- The address lookup table account data must be deserializable into
`AddressLookupTable` as defined in `solana-sdk`.
- All account table indices specified in the transaction must be less than
the number of active addresses in the address lookup table.
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be moved to the runtime error section. It's pretty straightforward to handle transactions with invalid address lookup tables in replay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Plan was for this to be in a separate follow-up SIMD since the choice here is very much not obvious imo.

How do we apply CUs to account-level cost if we cannot resolve ALTs?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with it being covered in a separate SIMD

proposals/0082-relax-transaction-constraints.md Outdated Show resolved Hide resolved
- OR the transaction must be a nonced transaction, and the nonce
account must exist and be valid for the given `recent_blockhash`.
12. The transaction must not have already been processed.
13. The transaction fee-payer account must:
Copy link
Contributor

Choose a reason for hiding this comment

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

We also need a section talking about durable nonce transactions. They must:

  • use a recent blockhash value different from the durable nonce for the current bank
  • have at least one transaction instruction, the first of which is designated the nonce advance instruction which must:
    • invoke the system program 11111111111111111111111111111111
    • have instruction data that deserializes to the SystemInstruction::AdvanceNonceAccount variant
    • have at least one account input, the first of which is designated the nonce address/account which must:
      • be loaded with a write-lock
      • be owned by the system program: 11111111111111111111111111111111
      • be deserializable to non-legacy initialized nonce state
      • have a durable nonce hash equal to the transaction's recent blockhash field
  • be signed by the nonce authority deserialized from the nonce account

Copy link
Contributor Author

Choose a reason for hiding this comment

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

proposals/0082-relax-transaction-constraints.md Outdated Show resolved Hide resolved
Copy link
Contributor

@jstarry jstarry left a comment

Choose a reason for hiding this comment

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

I think this SIMD can be trimmed down a lot and just focus on what I consider to be "transaction loading" constraints. We don't need to enumerate all of the protocol constraints in this document, so I think we should get rid of the "Current Protocol-Violation Errors" and the "Proposed Protocol-Violation Errors" sections which just leaves the "Proposed New Runtime Errors" section which is the only thing anyone will want to know when reading this document.

I know this SIMD started off as a general relax all the tx constraints proposal, but now that it's been scoped down, I think it should be renamed and focused to only relaxing account loading related transaction accounts. Which, in my opinion, includes all of the new runtime constraints you've listed with the exception of the precompile verification constrain which is already covered in #159

@apfitzge
Copy link
Contributor Author

apfitzge commented Aug 7, 2024

so I think we should get rid of the "Current Protocol-Violation Errors" and the "Proposed Protocol-Violation Errors" sections which just leaves the "Proposed New Runtime Errors" section which is the only thing anyone will want to know when reading this document.

Last review from Jump's side explicitly asked me to add in these which is why I did.
I'd much rather we had some central tracker of constraints so that SIMDs could be succint, and just update that when we make modificatons through accepted SIMDs.
But I think I will leave them in for now unless Jump's team decides they agree with that.

@apfitzge
Copy link
Contributor Author

This SIMD has been split into a few smaller SIMDs (biggest one being #191). Closing this issue since I will not be pushing for this to be merged. Discussions are not deleted and this PR is linked to from the split SIMD(s)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants