coral-xyz / anchor

⚓ Solana Sealevel Framework
https://anchor-lang.com
Apache License 2.0
3.36k stars 1.25k forks source link

Using `anchor_client` with `tokio` #3004

Open esolskjaer opened 4 weeks ago

esolskjaer commented 4 weeks ago

I'm trying to invoke a transaction with anchor_client from a tokio context. Here's how I'm doing it:

    let pid = Keypair::new().pubkey();
    let payer = Rc::new(Keypair::new());
    let client = Client::new_with_options(Cluster::Localnet, &payer, CommitmentConfig::processed());
    let program = client.program(pid).unwrap();
    // `Initialize` parameters.
    let dummy_a = Keypair::new();
    let dummy_b = Keypair::new();

    tokio::spawn(async {
        program
            .request()
            .accounts(CompositeUpdate {
                foo: Foo {
                    dummy_a: dummy_a.pubkey(),
                },
                bar: Bar {
                    dummy_b: dummy_b.pubkey(),
                },
            })
            .args(composite_instruction::CompositeUpdate {
                dummy_a: 1234,
                dummy_b: 4321,
            })
            .send()
            .await
            .unwrap();

        println!("Composite success!");
    });

Unfortunately this gives me the error

error[E0277]: `Rc<solana_sdk::signature::Keypair>` cannot be shared between threads safely
   --> src/nonblocking.rs:73:18
    |
73  |       tokio::spawn(async {
    |  _____------------_^
    | |     |
    | |     required by a bound introduced by this call
74  | |         program
75  | |             .request()
76  | |             .accounts(CompositeUpdate {
...   |
92  | |         println!("Composite success!");
93  | |     });
    | |_____^ `Rc<solana_sdk::signature::Keypair>` cannot be shared between threads safely
    |
    = help: within `anchor_client::Program<&Rc<solana_sdk::signature::Keypair>>`, the trait `Sync` is not implemented for `Rc<solana_sdk::signature::Keypair>`, which is required by `{async block@src/nonblocking.rs:73:18: 93:6}: Send`
    = note: required because it appears within the type `&Rc<solana_sdk::signature::Keypair>`

What I've tried:

This MRE is based on https://github.com/coral-xyz/anchor/blob/master/client/example/src/nonblocking.rs btw. The only change I made was adding tokio::spawn (since I need this in my own code) and enabling the async feature for anchor_client. Here's my fork with the mentioned changes: Just pushed an MRE for my issue here btw: https://github.com/esolskjaer/anchor/blob/master/client/example/src/nonblocking.rs#L65-L98

Any idea on how to fix this?

esolskjaer commented 4 weeks ago

After a lot of digging, I've found the root of the problem. Implemented a tentative solution here https://github.com/coral-xyz/anchor/pull/3006, but I think it still needs some work. I propose moving further discussion there.