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

Add proposal for Read-Only accounts that allow credits #2738

Merged
merged 1 commit into from
Mar 15, 2019

Conversation

aeyakovenko
Copy link
Member

@aeyakovenko aeyakovenko commented Feb 12, 2019

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

@aeyakovenko
Copy link
Member Author

@jackcmay

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.

@jackcmay
Copy link
Contributor

@aeyakovenko
Yes, is this a new proposal to exand the concept of read-only to being specified in the transaction. So that even if an account is owned by a program the transaction says it can not be modified?

@aeyakovenko
Copy link
Member Author

Yes, is this a new proposal to exand the concept of read-only to being specified in the transaction. So that even if an account is owned by a program the transaction says it can not be modified?

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.

@garious
Copy link
Contributor

garious commented Feb 13, 2019

This chapter describes the existing implementation. If you want to PR this chapter, it can't be merged until the implementation is updated.

@aeyakovenko
Copy link
Member Author

@jackcmay so the pipeline can't do the RO/RW check based on program id because the account is not loaded yet.

@aeyakovenko
Copy link
Member Author

@jackcmay

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.

@jackcmay
Copy link
Contributor

Can't rely completely on the transaction to determine RO vs RW, whats the alternative?

@aeyakovenko
Copy link
Member Author

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

@jackcmay
Copy link
Contributor

Doing away with the RO for non-owned accounts?

@aeyakovenko
Copy link
Member Author

Doing away with the RO for non-owned accounts?

no, just adding metadata to the TX field to speed up processing

@jackcmay
Copy link
Contributor

so if locks described in the TX don't jive after the accounts have been loaded bail?

@aeyakovenko
Copy link
Member Author

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.

book/src/SUMMARY.md Outdated Show resolved Hide resolved
@jackcmay
Copy link
Contributor

@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.
Copy link
Contributor

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?

Copy link
Member Author

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
Copy link
Contributor

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?

Copy link
Member Author

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
Copy link
Contributor

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?

Copy link
Member Author

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.
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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
Copy link
Contributor

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?

Copy link
Member Author

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?

Copy link
Contributor

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?

Copy link
Member Author

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."

Copy link
Contributor

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)

Copy link
Member Author

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.

book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
@aeyakovenko aeyakovenko added the work in progress This isn't quite right yet label Feb 14, 2019
@jackcmay
Copy link
Contributor

Approved with the agreed upon changes

@aeyakovenko aeyakovenko removed the work in progress This isn't quite right yet label Feb 15, 2019
@aeyakovenko aeyakovenko requested a review from mvines February 15, 2019 01:41
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved

* Read-only access to userdata.

Instructions that debit or modify the read only account userdata will fail.
Copy link
Member

Choose a reason for hiding this comment

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

nit: read-only account

book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
@aeyakovenko
Copy link
Member Author

@mvines @garious any more changes?

@garious
Copy link
Contributor

garious commented Feb 21, 2019

I haven't read it yet. Probably early next week. Did you want it in the book this release?

Copy link
Member

@mvines mvines left a 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, :shipit:

@aeyakovenko
Copy link
Member Author

@garious no rush

book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
@aeyakovenko
Copy link
Member Author

@garious, bump

Copy link
Contributor

@garious garious left a 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.

book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved

Read-only accounts have the following properties:

* Can be deposited into. Deposits can be implemented as a simple `atomic_add`.
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 why I've always refer to these accounts as "credit-only", not "read-only". Want to do the same in this doc?

Copy link
Member Author

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?

Copy link
Contributor

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.

Copy link
Contributor

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".

Copy link
Member Author

Choose a reason for hiding this comment

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

@garious

  • ROC, read-only-credit
  • RWW, read-write-withdraw

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 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.

Copy link
Member Author

@aeyakovenko aeyakovenko Mar 12, 2019

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

Copy link
Contributor

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.

Copy link
Member Author

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?

Copy link
Contributor

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.

book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
book/src/read-only-read-write-accounts.md Outdated Show resolved Hide resolved
@@ -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)
Copy link
Contributor

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.
Copy link
Contributor

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"

@garious
Copy link
Contributor

garious commented Mar 13, 2019

grammarly?

@garious
Copy link
Contributor

garious commented Mar 13, 2019

@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.

@aeyakovenko
Copy link
Member Author

@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.

@garious
Copy link
Contributor

garious commented Mar 14, 2019

Now can you check your grammarly commit for obvious misinterpretations?

Copy link
Contributor

@garious garious left a 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".

@garious
Copy link
Contributor

garious commented Mar 14, 2019

@aeyakovenko, I'll merge #3282 if I can get @mvines' approval. After that, can you rebase and replace mentions of "userdata" with "account data"?

@garious
Copy link
Contributor

garious commented Mar 14, 2019

@aeyakovenko, userdata-to-data PR now merged

@aeyakovenko aeyakovenko added the automerge Merge this Pull Request automatically once CI passes label Mar 15, 2019
@solana-grimes
Copy link
Contributor

💔 Unable to automerge due to CI failure

@solana-grimes solana-grimes removed the automerge Merge this Pull Request automatically once CI passes label Mar 15, 2019
@aeyakovenko aeyakovenko merged commit 0465abf into solana-labs:master Mar 15, 2019
joncinque pushed a commit to joncinque/solana that referenced this pull request Aug 27, 2024
* 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]>
jeffwashington pushed a commit to jeffwashington/solana that referenced this pull request Aug 27, 2024
* 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]>
jeffwashington pushed a commit to jeffwashington/solana that referenced this pull request Aug 27, 2024
* 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]>
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.

5 participants