-
Notifications
You must be signed in to change notification settings - Fork 4
feat: minimal rust delegate SDK #25
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
Conversation
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.
LGTM. The only comment/consideration is that tech stacks such as Rust programs with TypeScript unit tests won't use or need the added code (and vice versa; Rust clients don't need CPI and program integration utilities, and we could likely avoid some dependencies such as paste). However, the amount of code doesn't yet justify a separate crate for a Rust SDK. I’m OK with merging this now into the same crate and eventually refactoring into a separate crate if we end up adding more convenience code for Rust clients.
## Summary Implement schedule commit program and machinery to process it + send to chain. ## Details There are multiple pieces to the implementation: ### Sleipnir program instruction Schedule - allows any payer to schedule a commit via a CPI from the program that owns the PDAs we are trying to commit - multiple security checks are performed + the payer is deducted the assumed transaction cost to realize the commits on chain - that amount is credited to the validator authority - a _sent commit_ transaction is then created which only includes known factors, like the current blockhash, the ID of the commit and the keys to be committed - that transaction is executed in the next step, however its signature is logged at this point so that the user can request its logs and learn about the commit progress - the requested commits are added to a global queue of commits to be sent to the chain ### Sleipnir program instruction Scheduled Sent - at the next slot all queued commits are processed as follows - account states are checked and on chain transactions created to commit them (one transaction per queued commit), in the future we may need to split these into more transactions to avoid running over the maximum ix arg size - for each transaction we are about to send we _register_ the data we just determined, i.e. which keys are being committed and the signature of the chain transaction - the registration stores that data under the scheduled commit ID - we then execute the transaction created when the user scheduled the commit - this transaction looks up the _registered_ info and logs the following information - included committee keys - excluded committee keys - each signature needed to commit them on a separate line - this information can be parsed in order to extract usefull information, like the chain signature - once we executed those transactions for each commit we _actually_ send them to chain - at this point we hope for the best here, i.e. if chain is down we could run into either of the following, neither of which are signaled to the user at this point: - we cannot get the chain blockhash - the commit fails - see _Remaining_ on how we can improve on this ### Delagation SDK In order to properly create the delegate instruction I added a _start_ of a Rust SDK to the delegate program here: magicblock-labs/delegation-program#25 ### Trigger Commits The old way of triggering commits directly (instead of scheduling them) was removed as it is now obsolete and didn't work as we intended. ### Issues - I was unable to test the transfer of lamports from payer to validator since the `native_invoke` of the system program via CPI failed when using the `mock_transaction` feature - I tried different ways to get it added, but failed - integration tests take care of that though (see below) ### Tests Aside from the unit test I added integration tests which do the following. 1. Spin up a validator representing devnet 2. Spin up a validator representing ephem 3. Initialize two PDAs for a _wrapper_ program on _our_ devnet 4. Delegate those PDAs to the ephem 5. Schedule a commit from the _wrapper_ program on _our_ ephem, the wrapper also increases a `count` field on the account right before scheduling the commit via CPI 6. Verify the commit on _devnet_ (finding the signature by following the logs as explained above) 7. Verify both PDAs were included and committed with the count field increased 8. Verify that the payer was deducted the correct amount of lamports ## Unrelated - fix strum crate locations in `Cargo.toml` - I needed to ensure that the validator authority is never attempted to be cloned even if it is passes as a writable - without that fix I could not run the schedule commit transaction since the validator authority needs to be passes as a writable account in order to receive transaction fees (prospected on chain) ## Remaining ### Communicating Commit Outcome Tracked: #100 - in order to provide feedback if a commit could not be realized on chain we should add another transaction that logs commit outcome, i.e. `ScheduledCommitResult` - as with the `ScheduledCommitSent` we can use the _register_ pattern and thus are able to log the signature of that transaction at the time of schedule - users can then query the logs of the program to learn about the outcome of their commit ### Make CPI work with preloaded programs Tracked: #101 While setting up the integration tests I realized that CPI into a program that was _preloaded_ at validator start does not work. However when we clone it from chain on demand it does. I suspect this is due to an extra step we do in the cloning case. I will investigate this next and add a PR to fix this. NOTE: this does not affect Luzid workspaces as those are cloned the same way as onchain programs after the validator started up.
Summary
Initial minimal Rust SDK for account delegation.
Details
We don't have a Rust SDK at all at this point so here I added the minimum to make this somewhat
ergonomic to use.
With the added methods I can do the following to get the correctly initialized account metas
to include in the accounts sent to the wrapper instruction.
Remaining
The PDA derivation and
consts
have been copied for now with a note that we need to eithermove those into a core module or have the program use them via the sdk.