Skip to content

Conversation

thlorenz
Copy link
Contributor

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.

let (pda, _) = pda_and_bump(&player);

let delegate_accounts = DelegateAccounts::new(pda, program_id);
let delegate_metas = DelegateAccountMetas::from(delegate_accounts);
let account_metas = vec![
    AccountMeta::new(player, true),
    delegate_metas.delegate_account,
    delegate_metas.owner_program,
    delegate_metas.buffer,
    delegate_metas.delegation_record,
    delegate_metas.delegation_metadata,
    delegate_metas.delegation_program,
    delegate_metas.system_program,
];

Remaining

The PDA derivation and consts have been copied for now with a note that we need to either
move those into a core module or have the program use them via the sdk.

Copy link
Contributor

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

@thlorenz thlorenz merged commit 40f494d into main Jul 29, 2024
@thlorenz thlorenz deleted the thlorenz/rs-sdk-improvs branch July 29, 2024 09:20
thlorenz added a commit to magicblock-labs/magicblock-validator that referenced this pull request Aug 1, 2024
## 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.
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.

2 participants