ameliatastic / seahorse-lang

Write Anchor-compatible Solana programs in Python
Apache License 2.0
313 stars 43 forks source link

Fix use of account key() as seed #66

Closed mcintyre94 closed 1 year ago

mcintyre94 commented 1 year ago

The code we were generating was user . borrow () . __account__ . key () . as_ref (). But borrow() didn't exist on the boxed accounts that we end up with in the accounts struct.

Instead we can just use user.key().as_ref() directly.

Closes #62

ameliatastic commented 1 year ago

Does this still allow .key() to be used in non-seed contexts?

mcintyre94 commented 1 year ago

Oops looks like this needs a bit more work, I added this instruction:

@instruction
def hello(payer: Signer, user: User, another: Empty[Another]):
    a = another.init(payer, seeds=[user.key()])
    k = user.key()
    print(k)

And got this error:

anchor build -p seahorse_seeds failed:
   Compiling seahorse_seeds v0.1.0 (/Users/callum/scratch/seahorse_seeds/programs/seahorse_seeds)
error[E0599]: no method named `key` found for struct `seahorse_util::Mutable<LoadedUser<'info, '_>>` in the current scope
  --> programs/seahorse_seeds/src/dot/program.rs:85:22
   |
85 |     let mut k = user.key();
   |                      ^^^ method not found in `seahorse_util::Mutable<LoadedUser<'info, '_>>`
   |
  ::: programs/seahorse_seeds/src/lib.rs:25:5
   |
25 |     pub struct Mutable<T>(Rc<RefCell<T>>);
   |     -------------------------------------- method `key` not found for this
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `key`, perhaps you need to implement it:
           candidate #1: `anchor_lang::Key`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `seahorse_seeds` due to previous error

Marked this as draft, I'll take another look at this

ameliatastic commented 1 year ago

Just adding some thoughts, I think the very general problem here is that the AST (in the build step) is built bottom-up. This means that expressions like [account.key()] are completely built without any regard for the context that they're in, which might be a "normal" expression (keys = [account.key()]) or a "special" expression (my_account.init(seeds = [account.key()], ...).

So a full solution to this might require some real compiler rework. Maybe just pass down a context object to enable/disable certain behaviors and use that info to build up the AST?

mcintyre94 commented 1 year ago

I think it would need to be something like that, not sure exactly how that'd look though! IIRC didn't 0.1 have some special handling for seeds, where they'd be rendered specifically? I guess a generalised and more flexible version of that would be nice!

mcintyre94 commented 1 year ago

@ameliatastic I've refactored this, could you review please?

ameliatastic commented 1 year ago

Hey, really sorry I missed this, didn't realize you had brought this PR out of draft. Looking at it now!