solana icon indicating copy to clipboard operation
solana copied to clipboard

Cross-program balanced instruction handling is too restrictive

Open jackcmay opened this issue 5 years ago • 13 comments

Problem

The MessageProcessor's balanced instruction check ensures the Lamport sum of all accounts in the instruction remains the same before and after the instruction. Cross-program invocations only include the accounts required by the invoked instruction and thus leaves out any transfers the invoking program may have made to other accounts before the call to invoke.

For example:

For programs A and B and accounts X, Y, Z

  • A transfers lamports from X to Y
  • A invokes B passing Y, Z
  • balanced instruction check fails because it does not take into account the lamports in X

It requires developers to be aware of when they transfer tokens relative to any invocations they are making.

Proposed Solution

Include all accounts in the balance calculations

jackcmay avatar Apr 24 '20 18:04 jackcmay

@jstarry

jackcmay avatar Apr 24 '20 18:04 jackcmay

@jackcmay - do you want to keep this in 1.2 or punt to 1.3?

mvines avatar May 22 '20 06:05 mvines

@mvines I think given the other priorities punting to 1.3 is more realistic

jackcmay avatar May 22 '20 07:05 jackcmay

Looks like this is breaking Wormhole guardian set upgrades, which - if the subsidizer pool is full - do:

  • A CPI call.
  • Transfer lamports from the bridge's subsidizer pool.
  • Another CPI call.
[devnet] [2021-02-01T19:09:41.671877046Z DEBUG solana_runtime::message_processor] Program Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o invoke [1]
[devnet] [2021-02-01T19:09:41.672078448Z DEBUG solana_runtime::message_processor] Program log: Instruction: PostVAA
[devnet] [2021-02-01T19:09:41.673453480Z DEBUG solana_runtime::message_processor] Program log: deriving key
[devnet] [2021-02-01T19:09:41.673568861Z DEBUG solana_runtime::message_processor] Program log: deploying contract
[devnet] [2021-02-01T19:09:41.673794033Z DEBUG solana_runtime::message_processor] Program 11111111111111111111111111111111 invoke [2]
[devnet] [2021-02-01T19:09:41.673816843Z TRACE solana_runtime::system_instruction_processor] process_instruction: CreateAccount { lamports: 3814080, space: 420, owner: Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o }
[devnet] [2021-02-01T19:09:41.673826873Z TRACE solana_runtime::system_instruction_processor] keyed_accounts: [KeyedAccount { is_signer: true, is_writable: true, key: 6sbzC1eH4FTujJXWj51eQe25cYvr4xfXbJ1vAj7j2k5J, account: RefCell { value: Account { lamports: 99776482800 data.len: 0 owner: 11111111111111111111111111111111 executable: false rent_epoch: 0 } } }, KeyedAccount { is_signer: true, is_writable: true, key: 7h2RXNxM9r6NDvsxRXkn7rtGt2VNe6zcs5b74vbrhjkg, account: RefCell { value: Account { lamports: 0 data.len: 0 owner: 11111111111111111111111111111111 executable: false rent_epoch: 0 } } }]
[devnet] [2021-02-01T19:09:41.673851953Z DEBUG solana_runtime::message_processor] Program 11111111111111111111111111111111 success
[devnet] [2021-02-01T19:09:41.674085315Z DEBUG solana_runtime::message_processor] Program log: deriving key
[devnet] [2021-02-01T19:09:41.674340378Z DEBUG solana_runtime::message_processor] Program log: deploying contract
[devnet] [2021-02-01T19:09:41.674586211Z DEBUG solana_runtime::message_processor] Program Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o consumed 100351 of 200000 compute units
[devnet] [2021-02-01T19:09:41.674612091Z DEBUG solana_runtime::message_processor] Program Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o BPF VM error: sum of account balances before and after instruction do not match
[devnet] [2021-02-01T19:09:41.674620231Z DEBUG solana_runtime::message_processor] Program Bridge1p5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o failed: sum of account balances before and after instruction do not match

Reproduction instructions:

  • spawn fresh devnet with tilt up --update-mode=exec -- --num=1
  • run the E2E test suite to completion
  • run scripts/test-injection.sh 0 0, boom

leoluk avatar Feb 02 '21 12:02 leoluk

@leoluk One workaround is to do all in-program transfers at the end of a program's execution, is that possible here?

jackcmay avatar Feb 02 '21 16:02 jackcmay

Does anyone ever intend to fix this? I have not tried it yet but I think this means programs cannot do the following basic procedure:

  • transfer lamports to a wSOL token account by directly decrementing lamports from a program owned account
  • SyncNative the wSOL account

billythedummy avatar Dec 20 '23 10:12 billythedummy

+1 trying to do the exact same use case that @billythedummy speaks about.

transfer + sync native

It's not possible right now, so what is a workaround?

outdoteth avatar Jan 09 '24 12:01 outdoteth

Any updates on this one? I am also trying to:

  • transfer lamports to a wSOL token account by directly decrementing lamports from a program owned account
  • SyncNative the wSOL account

NikaTheEngineer avatar May 29 '24 22:05 NikaTheEngineer

Any updates on this one? I am also trying to:

  • transfer lamports to a wSOL token account by directly decrementing lamports from a program owned account
  • SyncNative the wSOL account

Now, I am also trying to do this. Do you have any resolution?

toptalhook avatar Jun 18 '24 16:06 toptalhook

@toptalhook The only thing you can do is wrap the SOL on a normal(non-program-owned) account and transfer wSOL to the program-owned account.

NikaTheEngineer avatar Jun 19 '24 10:06 NikaTheEngineer

Does anyone ever intend to fix this? I have not tried it yet but I think this means programs cannot do the following basic procedure:

  • transfer lamports to a wSOL token account by directly decrementing lamports from a program owned account
  • SyncNative the wSOL account

This is still not possible in 2024. Please, someone take a look.

b1acKr0se avatar Jul 03 '24 02:07 b1acKr0se