-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
Add proposal for Read-Only accounts that allow credits #2738
Conversation
8fdce45
to
d2405da
Compare
Don't we have a lot of this already for free? the loader should own the program executable bytes. and the accounts that are not owned by the program can only be "read-only". So we can do the same runtime optimization without an explicit flag. |
@aeyakovenko |
Yea, that is correct. Right now we don't do analysis to check for read-only accounts. I was thinking that if we end up needing full VM support, most of the memory necessary to execute a TX will be read only, like the page tables. |
This chapter describes the existing implementation. If you want to PR this chapter, it can't be merged until the implementation is updated. |
@jackcmay so the pipeline can't do the RO/RW check based on program id because the account is not loaded yet. |
The accounts are on disk or some faraway storage. A transaction batch is being processed. Each account takes a lock. For the runtime to decide if right there if its a RO or RW lock, the account needs to be fetched from far away storage and checked for its program id. |
Can't rely completely on the transaction to determine RO vs RW, whats the alternative? |
that's what I am proposing. The TX will say which accounts are RO, and the runtime can take the right lock before the account is loaded |
Doing away with the RO for non-owned accounts? |
no, just adding metadata to the TX field to speed up processing |
so if locks described in the TX don't jive after the accounts have been loaded bail? |
if the TX accounts are marked as RO, and the TX writes to them, then the transaction fails. But if an account is not marked RO and the TX reads them only, it still succeeds. |
@aeyakovenko These changes to account writability will need further changes to how we pass accounts to programs. We could split the RO and RW accounts into different parameters allowing the VM to abort on a write to RO. If we don't abort on write to RO at execution time we would not write back any RO accounts, but we probably also want a way to detect if there were any writes and fail the TX to avoid bad program states. |
The first account in the `account_keys` array is always the account that pays | ||
for the transaction fee, therefore it cannot be read-only. Since accounts can | ||
only appear once in the transaction's `account_keys` array, an account can only | ||
be read-only or read-write in a single transaction, not both. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So transactions that may want to pass an account to one program as RO and another as RW are invalid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay yea, because the runtime treats the TX as one thing, and if any instruction needs RW a copy needs to be made regardless and the write lock needs to be held for the entire pipeline.
only appear once in the transaction's `account_keys` array, an account can only | ||
be read-only or read-write in a single transaction, not both. | ||
|
||
* `program_ids: Vec<Pubkey>` - This vector is removed. Program keys can be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this imply that there is a one-to-one ordered relationship between the instructions in the transaction and the number of program keys placed at the end of account_keys
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay instructions reference the program id, so many instructions 1 program.
that account should fail. It follows that any other write lock requests will | ||
fail as well. | ||
|
||
## Alternative Design |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not following the alternative design. Says the purpose of the design is to no use a RO account list but then in 1. says there is a RO table. What is the difference between the list and table?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay one is a field in a Transcation structure, the other is a data structure in the bank to keep track of what is read-only.
|
||
1. Transaction accounts are locked. | ||
a. If the account is present in the `read-only` table the TX does not fail. | ||
The pending state for this TX is marked NeedReadLock. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So not failed but marked as pending and cached?
a. If the account is present in the `read-only` table the TX does not fail. | ||
The pending state for this TX is marked NeedReadLock. | ||
2. Transaction accounts are loaded. | ||
a. Transaction accounts that are read-only are increase their reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wording...
|
||
This design covers handling of read-only and read-write accounts in the | ||
[runtime](runtime.md). Accounts already distinguish themselves as read-only or | ||
read-write based on the instruction program. But to identify read-only accounts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the instruction program
? You means "transaction's instructions"?
accounts can be cached in memory and shared between all the threads executing | ||
transactions. | ||
|
||
The current runtime cannot predict if an account is read-only or read-write |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not following this, are you referring to the program's entry point? If so, by the time we call the program's entry point the accounts have been loaded and we know definitely if the account should be treated as RO or RW.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay before the fetch from storage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What entry point are you referring to? The current wording to me implies you are talking about program entry point, at that time we do know what locks we need since we've already pulled the account from storage.
placed at the end of the `account_keys` vector with the `read_only_accounts` | ||
number set to the right number of programs. | ||
|
||
## Starvation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this imply that no RW operations can be performed while an account is RO locked for other transactions being processed? If an account is continuously referenced for RO operations (multiple concurrent transactions) then all transactions that require RW to that account will fail during that time? Does that also imply that a cached RW request would stall the entire pipeline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay This section addresses starvation. Is that not clear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would like to see more detail here, for example, if a RW operation on a currently RO account is requested the pipeline will stall until the RW operation is performed? Does this cache RO requests that occur while the RW operation is being processed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay
"While a pending write transaction exists, any additional read lock requests for
that account should fail. It follows that any other write lock requests will
fail as well."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So then yes stall (serialize)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jackcmay not stall locally, the client's responsibility to retransmit.
Approved with the agreed upon changes |
|
||
* Read-only access to userdata. | ||
|
||
Instructions that debit or modify the read only account userdata will fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: read-only account
I haven't read it yet. Probably early next week. Did you want it in the book this release? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good enough for me,
@garious no rush |
7e79c0b
to
d651104
Compare
@garious, bump |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can accelerate the review process by grammar-checking before the engineering review.
|
||
Read-only accounts have the following properties: | ||
|
||
* Can be deposited into. Deposits can be implemented as a simple `atomic_add`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why I've always refer to these accounts as "credit-only", not "read-only". Want to do the same in this doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think how memory is treated is the more significant part. RC, read-credit? RWW, read-withdraw-write?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about credit-only and credit-debit accounts? How memory is treaded is only the more significant part of this particular proposal. How currency is handled might be more significant to users. In any case, we should always aim to CIWII, and because the runtime allows lamports to increase, it's imprecise to call the account read-only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny how even your title would become short and sweet if you used "credit-only". Instead of "Add proposal for Read-Only accounts that allow credits" it'd reduce to "Add proposal for credit-only accounts".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- ROC, read-only-credit
- RWW, read-write-withdraw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's unnecessarily verbose. These are attributes of things called "accounts". You could say that the userdata of a credit-only account is read-only, and the userdata of a credit-debit account is read-write. Introducing acronyms here is not necessary or helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@garious it helps to identify the accounts referenced in instructions as RO or RW, most of the time the token's are not important because the data is what is observed. Do you want to identify them as C, or W?
For example
ExchangeInstruction::Match
account[0] - R - Trade[0] address
account[1] - RW - Match address from Trade[0]
account[2] - R - Trade[1] address
account[3] - RW - Match address from Trade[1]
being explicit about what is RW or not is really helpful with designing the instruction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
R and RW seems fine there. You're referring to the userdata.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@garious yea, so what is the convention we want to use? I'd like to have a standard one that is not to verbose. CO/CD?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, CO/CD. Let's just be consistent in case we want to globally search and replace it later.
d651104
to
1fb7ac1
Compare
book/src/SUMMARY.md
Outdated
@@ -39,6 +39,8 @@ | |||
- [Secure Vote Signing](vote-signing-to-implement.md) | |||
- [Staking Rewards](staking-rewards.md) | |||
- [Fork Selection](fork-selection.md) | |||
- [Data Plane Fanout](data-plane-fanout.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rebase fail?
|
||
* Can be deposited into. Deposits can be implemented as a simple `atomic_add`. | ||
|
||
* Read-only access to userdata. | ||
* credit-only access to userdata. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Userdata should be "read-only"
grammarly? |
@aeyakovenko, if we implement credit-only program accounts, the userdata will be read-write. Therefore there'd be read-only accounts (loaders), credit-only accounts with read-only userdata (system programs), and credit-only accounts with read-write userdata. |
@garious there isn't a technical requirement for loaders to be read-only accounts. they can function as credit-only. |
Now can you check your grammarly commit for obvious misinterpretations? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the nits to reverse some of the grammarly changes. Put the hyphen back in "credit only" and return "user data" to "userdata".
@aeyakovenko, I'll merge #3282 if I can get @mvines' approval. After that, can you rebase and replace mentions of "userdata" with "account data"? |
@aeyakovenko, userdata-to-data PR now merged |
bf75380
to
7ac8438
Compare
7ac8438
to
46c1b5c
Compare
💔 Unable to automerge due to CI failure |
* build(deps): bump serde from 1.0.208 to 1.0.209 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.208 to 1.0.209. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](serde-rs/serde@v1.0.208...v1.0.209) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> * Update all Cargo files * sync --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: yihau <[email protected]>
* build(deps): bump serde from 1.0.208 to 1.0.209 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.208 to 1.0.209. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](serde-rs/serde@v1.0.208...v1.0.209) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> * Update all Cargo files * sync --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: yihau <[email protected]>
* build(deps): bump serde from 1.0.208 to 1.0.209 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.208 to 1.0.209. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](serde-rs/serde@v1.0.208...v1.0.209) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> * Update all Cargo files * sync --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: yihau <[email protected]>
Problem
Transactions lock and commit all accounts. If they specified a set of read-only accounts its possible for multiple concurrent transactions to credit those accounts as well as read their state. The runtime cannot check if an Account will be used as RO/RW based on program id because the account is not loaded when it is locked.
With this general purpose solution program ids will be treated as read-only accounts, appropriately cached in the runtime, and remove the need for a dedicated program ids vector in the Transaction structure.
This proposal doesn't change the underlying runtime rules, that non-owned accounts are RO. It is simply a hint to the runtime that accounts referenced in the transaction are RO and not RW.
Summary of Changes
Propose a simple design to specify the read-only keys in a transaction. Programs can be treated as read-only keys.
Fixes #
tag: @garious @mvines