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

Propose traced transaction construction #17796

Closed

Conversation

ryoqun
Copy link
Member

@ryoqun ryoqun commented Jun 7, 2021

(boring meta-joke due to imminent sleep time.)

Problem

This is half-done!

Summary of Changes

Push more commitz and squaz

context (original idea is written when the itoken reviewing: #15927 (comment))


## Problem

With more composition comes in the Solana's program ecosystem, it will be harder
Copy link
Member Author

Choose a reason for hiding this comment

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

this doc is still in the draft phase. but I think the first half of this is written decently. ;)


## Future possible expansions

- Wallet account balance delta check: append VerifyTokenBalances ix at last and pass the expected balances of spl-tokens or hash of it (also with delegation status).
Copy link
Member Author

Choose a reason for hiding this comment

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

this is my (hopefully nice) solution to this: #17762

Copy link
Member Author

Choose a reason for hiding this comment

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

also, dynamic ix append as directed traced simulation might also be useful.

## Future possible expansions

- Wallet account balance delta check: append VerifyTokenBalances ix at last and pass the expected balances of spl-tokens or hash of it (also with delegation status).
- Browser-side bpf program simualtion for server-less architecture with online wasm translation
Copy link
Member Author

Choose a reason for hiding this comment

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

this is only possible because solana tx execution doesn't touch the whole account state in the chain. :)

This reduces the number of required accounts for CPI and clients from 7 to 3, reducing by 4.
(Obviously, we can't actually deploy these changes because this will break
compatibility. This is only for illustration of effective applicability to
moderately-complex program construct.)
Copy link
Member Author

@ryoqun ryoqun Jun 7, 2021

Choose a reason for hiding this comment

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

also, maybe worth to mention that this doesn't reduce the resultant tx binary size, we need still this badly for more composability: #15927 cc: @jstarry

The good thing is that this nor the page-indexed tx block each other. :)


prevent program detect to be simulated or really-executed


Copy link
Member Author

Choose a reason for hiding this comment

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

also, write about the strip of is_signer and no use case limited by this stripping.

deployed programs can be now upgradeable. This severely hampers ongoing
consumed-program's implementation refinement in the areas of data migration and
improved concurrency, by preventing transparent account switching and
sharding with vectorized accounts, respectively.
Copy link
Member

Choose a reason for hiding this comment

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

what is meant by "vectorized 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.

@jstarry don't be bothered with it.. ;) well, I used this fancy adjective, remotely referencing the usage like vectorization with SSE4/AVX2. Maybe sharding by itself should be enough.

Sharding here means avoiding write lock to the same internal account by using different accounts to write by deriving from the first byte of other account addresses like order_id for DEX. So, program can avoid write lock contention easily. Also, see the sharding example for code.

I want to say, hiding internal account addresses in this way makes these optimizations can be introduced by drop-in basis.

Copy link
Member

Choose a reason for hiding this comment

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

Ah got it, I like the idea of abstracting away implementation details like this, thanks for the explanation!

can be traced:

```rust
fn access_as_unsigned(address: &Pubkey, flags = enum { READ, WRITE}):
Copy link
Member Author

@ryoqun ryoqun Jun 12, 2021

Choose a reason for hiding this comment

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

Considering this #17901,

Maybe we should augment this by returning enum {AccountInfo, AccountRef} with new flag ACCESS_AS_REF. so that we can avoid any serializing into program execution environment.

AccountRef can only be used for passing to child cpi.

program_id,
);
let transfer_counter = access_as_unsigned(counter_address, READ_WRITE)?;
let clock_sysvar = access_as_unsigned(sysvars::clock::id(), 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.

Why is clock rw?

],
program_id,
);
let transfer_counter = access_as_unsigned(counter_address, 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.

What type is transfer_counter?

@jackcmay
Copy link
Contributor

This is interesting. I like that it reduces and simplifies a program's calling interface by hiding internal-only accounts that the caller doesn't need to be or shouldn't be aware of.

@jackcmay
Copy link
Contributor

In addition to a syscall used to discover dependent accounts, if any cpi is invoked during simulation that specifies new accounts, those new accounts should also be added to the list. During non-simulation those dependent accounts would be listed in the tx, loaded along with the rest of the accounts and referenced as needed.

@stale
Copy link

stale bot commented Jun 22, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jun 22, 2021
@stale
Copy link

stale bot commented Jul 1, 2021

This stale pull request has been automatically closed. Thank you for your contributions.

@stale stale bot closed this Jul 1, 2021
@ryoqun ryoqun reopened this Jul 12, 2021
@stale stale bot removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jul 12, 2021
@@ -22,13 +22,12 @@ pub fn process_instruction(
let account_info_iter = &mut accounts.iter();

let funder_info = next_account_info(account_info_iter)?;
Copy link
Member Author

Choose a reason for hiding this comment

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

related to #18588

@@ -0,0 +1,247 @@
# Traced transaction construction via RPC's `simulateTransaction`
Copy link
Member Author

Choose a reason for hiding this comment

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

traced => instrumented?

@stale
Copy link

stale bot commented Jul 21, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jul 21, 2021
@ruuda
Copy link
Contributor

ruuda commented Jul 21, 2021

Tracing can only reveal references in code that is actually executed. Consider something like

let clock = Clock::get()?;
if clock.slot % 2 == 0 {
    reference_account_a();
} else {
    reference_account_b();
}

If the RPC traces the program execution and says it referenced account A, then it is likely that by the time it executes for real, the program will try to reference account B.

This is similar to how tests can only reveal bugs in code that is executed; to get an exhaustive answer, you need some kind of (static) program analysis or abstract interpretation.

@stale stale bot removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jul 21, 2021
@ryoqun
Copy link
Member Author

ryoqun commented Jul 22, 2021

Tracing can only reveal references in code that is actually executed. Consider something like

let clock = Clock::get()?;
if clock.slot % 2 == 0 {
    reference_account_a();
} else {
    reference_account_b();
}

If the RPC traces the program execution and says it referenced account A, then it is likely that by the time it executes for real, the program will try to reference account B.

This is similar to how tests can only reveal bugs in code that is executed; to get an exhaustive answer, you need some kind of (static) program analysis or abstract interpretation.

@ruuda thanks for chiming in! you're first penguin from community. I really appreciate that.

Yeah, I understand the limitation. You have a point. But I still think this proposal could be reasonable solution for the problems described, at the cost of the strict requirement of rpc's simulation when issuing transactions to any advanced programs.

Maybe I should have added a prose like this?:

# Limitations (or Compromises)

This facility must not be abused and used wisely, needing proper developer
guidelines/communication. Firstly, dynamic account selection logic shouldn't
be timing sensitive or not change frequently. Because there is unavoidable
timing delays between simulation and actual execution on chain, transactions
could fail unexpectedly if implemented badly.

In other words, while dynamic account loading could give greater flexibility, the
logic should rather be static over time and for individual user sessions. The dynamic loading
isn't goal par itself. Rather this proposal tries to reduce and simplify a program's
calling interface by hiding internal-only accounts that the caller doesn't need to be or
shouldn't be aware of.

# Alternatives

- Some (static) IDL/DSL for account loading logic: hard to develop/design to cover any conceivable use cases. extra complexity
- provide no programmatic/systemic way to describe account loading (status quo): hard to compose defi programs. 

How do you like?


race condition around program deploy (= possible account loading change) => just retry also seek to the ix versioning for perfection

(traced program just load dummy addresses for tx versionsing for completeness)
Copy link
Member Author

Choose a reason for hiding this comment

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

also, I have to embed this pr comment into doc: #17796 (comment)

@ruuda
Copy link
Contributor

ruuda commented Jul 23, 2021

How do you like?

I don’t have a strong opinion on it, I just wanted to point out the limitation. Personally I think that with the way the Solana runtime is exposed to Rust at the moment, Rust is not a great language for writing Solana programs, and in the long run I expect some DSL to take over. A DSL could take care of those details internally, with a compiler figuring out which accounts are referenced.

@stale
Copy link

stale bot commented Jul 30, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Jul 30, 2021
@stale
Copy link

stale bot commented Aug 10, 2021

This stale pull request has been automatically closed. Thank you for your contributions.

@stale stale bot closed this Aug 10, 2021
@ryoqun ryoqun mentioned this pull request Aug 13, 2021
@ryoqun ryoqun reopened this Aug 18, 2021
@stale stale bot removed the stale [bot only] Added to stale content; results in auto-close after a week. label Aug 18, 2021
@stale
Copy link

stale bot commented Aug 28, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Aug 28, 2021
@stale
Copy link

stale bot commented Sep 4, 2021

This stale pull request has been automatically closed. Thank you for your contributions.

@stale
Copy link

stale bot commented Sep 19, 2021

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Sep 19, 2021
@mvines mvines closed this Feb 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale [bot only] Added to stale content; results in auto-close after a week.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants