From 2025d8469f5e2d29adf4725a2b481a22fb9aed86 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 7 Jun 2021 23:19:20 +0900 Subject: [PATCH 1/9] Propose traced transaction construction --- .../traced-transaction-construction.md | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 docs/src/proposals/traced-transaction-construction.md diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md new file mode 100644 index 00000000000..d5b9649132d --- /dev/null +++ b/docs/src/proposals/traced-transaction-construction.md @@ -0,0 +1,217 @@ +# Traced transaction construction via RPC's transaction simulation + +## Problem + +With more composition comes, it will be harder and harder for the higher-level +consumer to correctly construct high-level transactions by precisely specifying +each and every accessed accounts with the `read_only` or `read_write` proper +flag. + +Also, there will be no way to signal the need of additional accounts for the +arbitrarily customized behavior from the lower-level program to the higher-level +one under the standardized instruction API like spl-token, even though we're +about to explore the flexibility of allowing custom programs conforming to a +standard like itoken. + +The preceding runtime limitation are applicable both to on-chain (instruction +construction for CPI) or off-chain (transaction construction by end-user +interfaces) boundaries likewise. + +Lastly, it's practically impossible to change those accessed account addresses +once deployed while retaining compatibility, given the fact the consumers are +expected to hard-code the account addresses for consumption, even if the +deployed programs can be now upgradeable. This severely hampers ongoing +consumed-program's implementation refinement in the areas of data migration and +improved concurrency, by preventing transparent account switching and +sharding with vectorized accounts, respectively. + +## Proposed Solution + +Extend the `simulateTransaction` RPC method to return more information like +additional account addresses to read and/or write, collected from traced +transaction execution in the simulation. + +After that, client signs the final transaction after appending these additional +account addresses and submits it to the cluster via `sendTransaction`. + +In other words, programs can dynamically access their _internal_ accounts +implicitly via the newly-added traced syscalls. + +## Traced syscalls + +The runtime exposes new syscall to provide new account access mechanism which +can be traced: + +```rust +fn access_as_unsigned(address: &Pubkey, flags = enum { READ, WRITE}): + Result { ... } +// NOTE: accessing to signed account in this way will strip the is_signer bit. +// hence that's reflected in the name +``` + +This syscall behaves differently depending on the BPF execution mode (simulated +or executed): + +simulated: load any account at the specified address (if any) and retain any +written data to those accounts in the scope of single transaction simulation. + +executed: load any account if the specified address is contained in the list of +tx's account keys. + +While MessageProcessor's `verify_accounts` is enforced to these accessed +accounts like normally-accessed accounts, this syscall can bypass the CPI +boundaries by always accessing to the outermost execution environment (the +whole AccountsDB account set while simulated, all of account keys while +executed). This bypass semantics is needed to work with existing CPI. + +Then, otherwise noted, the returned AccountInfo should behave exactly same both +in the simulated and executed mode. This is desired for determisnism for +developers and is mandated for security to lightly protect users from bad +programs pretending to be harmless only in simulation. + + +## example: the associated token account program (demonstrating the problem #1) + +```patch +$ git diff +diff --git a/associated-token-account/program/src/processor.rs b/associated-token-account/program/src/processor.rs +index 98eb08b..ff0ad5b 100644 +--- a/associated-token-account/program/src/processor.rs ++++ b/associated-token-account/program/src/processor.rs +@@ -22,13 +22,11 @@ pub fn process_instruction( + let account_info_iter = &mut accounts.iter(); + + let funder_info = next_account_info(account_info_iter)?; +- let associated_token_account_info = next_account_info(account_info_iter)?; + let wallet_account_info = next_account_info(account_info_iter)?; + let spl_token_mint_info = next_account_info(account_info_iter)?; +- let system_program_info = next_account_info(account_info_iter)?; +- let spl_token_program_info = next_account_info(account_info_iter)?; +- let spl_token_program_id = spl_token_program_info.key; +- let rent_sysvar_info = next_account_info(account_info_iter)?; ++ let system_program_info = access_as_unsigned(funder_info.owner(), READ)?; ++ let spl_token_program_info = access_as_unsigned(spl_token_mint_info.owner(), READ)?; ++ let rent_sysvar_info = access_as_unsigned(sysvars::rent::id(), READ)?; + + let (associated_token_address, bump_seed) = get_associated_token_address_and_bump_seed_internal( + &wallet_account_info.key, +@@ -36,10 +34,7 @@ pub fn process_instruction( + program_id, + &spl_token_program_id, + ); +- if associated_token_address != *associated_token_account_info.key { +- msg!("Error: Associated address does not match seed derivation"); +- return Err(ProgramError::InvalidSeeds); +- } ++ let associated_token_account_info = access_as_unsigned(associated_token_address, READ_WRITE)?; + + let associated_token_account_signer_seeds: &[&[_]] = &[ + &wallet_account_info.key.to_bytes(), +``` + +This reduces the number of require accounts for CPI and clients from 7 to 3, reducing 4. + +## example: limited number of NFT transfers per day shared across program: + +```rust +pub fn process_transfer( + program_id: &Pubkey, + accounts: &[AccountInfo], + amount: u64, + expected_decimals: Option, +) -> ProgramResult { + let counter_address = Pubkey::find_program_address( + &[ + &program_id.to_bytes(), + "counter", + ], + program_id, + ); + let transfer_counter = access_as_unsigned(counter_address, READ_WRITE)?; + let clock_sysvar = access_as_unsigned(sysvars::clock::id(), READ_WRITE)?; + let today = yyyymmdd(clock_sysvar); + if today > transfer_counter.yyyymmdd { + transfer_counter.yymmdd = today; + transfer_counter.count = 0; + } else if transfer_counter > 10 { + return Err("daily quote of transfer is reached"); + } + + ... +} +``` + + +## example: sharding + + +```rust +pub fn process_place_order( + program_id: &Pubkey, + market_id: &Pubkey, + order: &Pubkey, +) { + let sharded_event_queue = let counter_address = Pubkey::find_program_address( + &[ + &market_id.to_bytes(), + &[ourder_to_bytes()[0] & 0xf0], + ], + program_id, + ); +} +``` + +## RPC changes + +`pre_balances` and `post_balances` needs to be updated? + +sample return from simulatedTransaction: + +```yml +# these somewhat verbose formatting is for future expansion +transaction: + instructions + accesses: + Bm9UhRBysjeT35ukzriheHKr76yiM1fPyEBMMw2yT9v1: {read: true, write: false} + J8H1Gsvnm2CY5oVa1zw1LHHbfvtone8ZGsVBzjkkPbpy: {read: true, write: true} + instructions: + accounts: [] + instruction_type: spl_token_transfer + instructions: [...] + accesses: [...] + pre_balances/pre_token_balances + post_balances/post_token_balances + token_approvals +``` + + + +also, page-indexed account can be incorporated to find compact combination of existing account indexes to match the required account list + + +## Other Proposals / alternative implementation + + +# or customized entrypoint? + +## careful consideration + +prevent program to be simulated or really-executed + +## downside + +race condition around program deploy (= possible account loading change) => just retry +also, traced program just load dummy addresses for tx versionsing for completeness + +# Run these before replaying stage on validator + +unavoidable latency. + + + + + +# Future expansion + +Wallet account delta check +Browser-side bpf program simualtion for server-less architecture with online wasm translation From 41c9057e4a93e99a124ba3a912821e2c6ad8f683 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 7 Jun 2021 23:37:46 +0900 Subject: [PATCH 2/9] Tweak --- .../traced-transaction-construction.md | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index d5b9649132d..9b56c799818 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -2,18 +2,18 @@ ## Problem -With more composition comes, it will be harder and harder for the higher-level -consumer to correctly construct high-level transactions by precisely specifying -each and every accessed accounts with the `read_only` or `read_write` proper -flag. +With more composition for Solana's program comes, it will be harder and harder +for the higher-level consuming program to correctly construct lower-level +program's instructions by precisely specifying each and every accessed accounts +with the `read_only` or `read_write` flag. Also, there will be no way to signal the need of additional accounts for the arbitrarily customized behavior from the lower-level program to the higher-level one under the standardized instruction API like spl-token, even though we're -about to explore the flexibility of allowing custom programs conforming to a -standard like itoken. +about to explore the flexibility of allowing customzed programs conforming to a +standard like the itoken. -The preceding runtime limitation are applicable both to on-chain (instruction +These preceding runtime limitations are applicable both to on-chain (instruction construction for CPI) or off-chain (transaction construction by end-user interfaces) boundaries likewise. @@ -141,7 +141,6 @@ pub fn process_transfer( } ``` - ## example: sharding @@ -161,6 +160,23 @@ pub fn process_place_order( } ``` +### example: instruction versioning by traced access after redeploy + +``` +pub fn check_instruction_version_and_load_data() { + // this is newly added after the redeploy + if access_as_unsigned(declare!("OldVersion111111111111111111111111111111111111"), READ).is_ok() { + return Err("we changed internal data loading implementation. to avoid unexpected malfunction retry"); + } + + // this is changed from OldVersion1111 + access_as_unsigned(declare!("NewVersion111111111111111111111111111111111111"), READ)? + + access_as_unsigned(...); +} +``` + + ## RPC changes `pre_balances` and `post_balances` needs to be updated? From 89efda342ee4587f2746dbcdfa2f284979292c86 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 7 Jun 2021 23:47:25 +0900 Subject: [PATCH 3/9] Tweak --- .../traced-transaction-construction.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index 9b56c799818..c60593e0817 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -2,10 +2,10 @@ ## Problem -With more composition for Solana's program comes, it will be harder and harder -for the higher-level consuming program to correctly construct lower-level -program's instructions by precisely specifying each and every accessed accounts -with the `read_only` or `read_write` flag. +With more composition comes in the Solana's program ecosystem, it will be harder +and harder for the higher-level consuming program to correctly construct +lower-level program's instructions by precisely specifying each and every +accessed accounts with the `read_only` or `read_write` flag. Also, there will be no way to signal the need of additional accounts for the arbitrarily customized behavior from the lower-level program to the higher-level @@ -34,8 +34,9 @@ transaction execution in the simulation. After that, client signs the final transaction after appending these additional account addresses and submits it to the cluster via `sendTransaction`. -In other words, programs can dynamically access their _internal_ accounts -implicitly via the newly-added traced syscalls. +For that end, introduce a new syscall to trace account accesses, so that +programs can dynamically hint their _internal_ or _derivable_ account addresses +implicitly via , attaning the classic implementation-detail abstraction. ## Traced syscalls @@ -221,9 +222,8 @@ also, traced program just load dummy addresses for tx versionsing for completene # Run these before replaying stage on validator -unavoidable latency. - - +unavoidable latency. (and scheduling difficulty). +The proposed implementation doesn't have such a downside From 2580dddc7a3b49a5808fe45b7e32f214a62624ec Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 7 Jun 2021 23:50:05 +0900 Subject: [PATCH 4/9] Tweak --- docs/src/proposals/traced-transaction-construction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index c60593e0817..e43068be65c 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -1,4 +1,4 @@ -# Traced transaction construction via RPC's transaction simulation +# Traced transaction construction via RPC's `simulateTransaction` ## Problem From 3b926fd52dad426458d0c7f703f2d0562dce91b7 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Tue, 8 Jun 2021 00:05:37 +0900 Subject: [PATCH 5/9] Tweak --- .../traced-transaction-construction.md | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index e43068be65c..ee8eecf3a96 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -31,7 +31,7 @@ Extend the `simulateTransaction` RPC method to return more information like additional account addresses to read and/or write, collected from traced transaction execution in the simulation. -After that, client signs the final transaction after appending these additional +Then, client signs the final transaction after appending these additional account addresses and submits it to the cluster via `sendTransaction`. For that end, introduce a new syscall to trace account accesses, so that @@ -53,33 +53,33 @@ fn access_as_unsigned(address: &Pubkey, flags = enum { READ, WRITE}): This syscall behaves differently depending on the BPF execution mode (simulated or executed): -simulated: load any account at the specified address (if any) and retain any -written data to those accounts in the scope of single transaction simulation. +simulated: load any account at the specified address from AccountsDb (if any) +and retain any written data to those accounts in the scope of single transaction +simulation. -executed: load any account if the specified address is contained in the list of +executed: return any account if the specified address is contained in the list of tx's account keys. While MessageProcessor's `verify_accounts` is enforced to these accessed accounts like normally-accessed accounts, this syscall can bypass the CPI boundaries by always accessing to the outermost execution environment (the whole AccountsDB account set while simulated, all of account keys while -executed). This bypass semantics is needed to work with existing CPI. +executed). This bypass semantic is needed to work with existing CPI usage. -Then, otherwise noted, the returned AccountInfo should behave exactly same both -in the simulated and executed mode. This is desired for determisnism for -developers and is mandated for security to lightly protect users from bad -programs pretending to be harmless only in simulation. +Then, otherwise noted, the returned `AccountInfo` should behave in the exactly +same way both in the simulated and executed mode. This is desired for +determisnism while developing and is mandated for security to lightly protect +users from bad programs pretending to be harmless only in simulation. ## example: the associated token account program (demonstrating the problem #1) ```patch -$ git diff diff --git a/associated-token-account/program/src/processor.rs b/associated-token-account/program/src/processor.rs -index 98eb08b..ff0ad5b 100644 +index 98eb08b..fa8ae50 100644 --- a/associated-token-account/program/src/processor.rs +++ b/associated-token-account/program/src/processor.rs -@@ -22,13 +22,11 @@ pub fn process_instruction( +@@ -22,13 +22,12 @@ pub fn process_instruction( let account_info_iter = &mut accounts.iter(); let funder_info = next_account_info(account_info_iter)?; @@ -88,15 +88,15 @@ index 98eb08b..ff0ad5b 100644 let spl_token_mint_info = next_account_info(account_info_iter)?; - let system_program_info = next_account_info(account_info_iter)?; - let spl_token_program_info = next_account_info(account_info_iter)?; -- let spl_token_program_id = spl_token_program_info.key; -- let rent_sysvar_info = next_account_info(account_info_iter)?; + let system_program_info = access_as_unsigned(funder_info.owner(), READ)?; + let spl_token_program_info = access_as_unsigned(spl_token_mint_info.owner(), READ)?; + let spl_token_program_id = spl_token_program_info.key; +- let rent_sysvar_info = next_account_info(account_info_iter)?; + let rent_sysvar_info = access_as_unsigned(sysvars::rent::id(), READ)?; let (associated_token_address, bump_seed) = get_associated_token_address_and_bump_seed_internal( &wallet_account_info.key, -@@ -36,10 +34,7 @@ pub fn process_instruction( +@@ -36,10 +35,7 @@ pub fn process_instruction( program_id, &spl_token_program_id, ); @@ -110,7 +110,7 @@ index 98eb08b..ff0ad5b 100644 &wallet_account_info.key.to_bytes(), ``` -This reduces the number of require accounts for CPI and clients from 7 to 3, reducing 4. +This reduces the number of required accounts for CPI and clients from 7 to 3, reducing by 4. ## example: limited number of NFT transfers per day shared across program: @@ -136,6 +136,8 @@ pub fn process_transfer( transfer_counter.count = 0; } else if transfer_counter > 10 { return Err("daily quote of transfer is reached"); + } else { + transfer_counter.count += 1; } ... @@ -151,19 +153,22 @@ pub fn process_place_order( market_id: &Pubkey, order: &Pubkey, ) { - let sharded_event_queue = let counter_address = Pubkey::find_program_address( - &[ - &market_id.to_bytes(), - &[ourder_to_bytes()[0] & 0xf0], - ], - program_id, - ); + let sharded_event_queue_address = let counter_address = Pubkey::find_program_address( + &[ + &market_id.to_bytes(), + &[ourder_to_bytes()[0] & 0xf0], + ], + program_id, + ); + let event_queue = access_as_unsigned(sharded_event_queue_address, READ_WRITE); + + // crank tx will merge all event queues later } ``` -### example: instruction versioning by traced access after redeploy +### example: instruction versioning across redeploy -``` +```rust pub fn check_instruction_version_and_load_data() { // this is newly added after the redeploy if access_as_unsigned(declare!("OldVersion111111111111111111111111111111111111"), READ).is_ok() { From fc2e41162fa5671556571d29b0ed1633fad6769f Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Tue, 8 Jun 2021 00:09:32 +0900 Subject: [PATCH 6/9] Tweak --- docs/src/proposals/traced-transaction-construction.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index ee8eecf3a96..83809a3eaa3 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -34,6 +34,10 @@ transaction execution in the simulation. Then, client signs the final transaction after appending these additional account addresses and submits it to the cluster via `sendTransaction`. +To be specific, wallet should be able to manage these transaction finalization, +agnostic to individual defi programs. This extra simulation process results in +no-op if the executed program aren't aware of this new functionality. + For that end, introduce a new syscall to trace account accesses, so that programs can dynamically hint their _internal_ or _derivable_ account addresses implicitly via , attaning the classic implementation-detail abstraction. From cd2fc6d11472a76691adb750c99c3a3e8c546c56 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Tue, 8 Jun 2021 00:28:53 +0900 Subject: [PATCH 7/9] Tweak --- .../traced-transaction-construction.md | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index 83809a3eaa3..d4e57cf844b 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -34,13 +34,15 @@ transaction execution in the simulation. Then, client signs the final transaction after appending these additional account addresses and submits it to the cluster via `sendTransaction`. -To be specific, wallet should be able to manage these transaction finalization, -agnostic to individual defi programs. This extra simulation process results in -no-op if the executed program aren't aware of this new functionality. - For that end, introduce a new syscall to trace account accesses, so that programs can dynamically hint their _internal_ or _derivable_ account addresses -implicitly via , attaning the classic implementation-detail abstraction. +implicitly, attaning the classic implementation-detail abstraction in the +context Soalna's program ecosystem. + +In general, wallets should be able to manage these transaction finalization, +agnostic to individual defi programs. Also, this extra simulation step results +in no-op and harmless if all of the executed programs aren't aware of this new +functionality. ## Traced syscalls @@ -76,7 +78,7 @@ determisnism while developing and is mandated for security to lightly protect users from bad programs pretending to be harmless only in simulation. -## example: the associated token account program (demonstrating the problem #1) +### example: the associated token account program (demonstrating the problem #1) ```patch diff --git a/associated-token-account/program/src/processor.rs b/associated-token-account/program/src/processor.rs @@ -115,8 +117,11 @@ index 98eb08b..fa8ae50 100644 ``` This reduces the number of required accounts for CPI and clients from 7 to 3, reducing by 4. +(Obviously, we can't actually deploy these changes because this will break +compatibility. This is only for illustration of effective applicability to +moderately-complex program construct.) -## example: limited number of NFT transfers per day shared across program: +### example: limited number of NFT transfers per day shared across program: ```rust pub fn process_transfer( @@ -140,15 +145,14 @@ pub fn process_transfer( transfer_counter.count = 0; } else if transfer_counter > 10 { return Err("daily quote of transfer is reached"); - } else { - transfer_counter.count += 1; } + transfer_counter.count += 1; ... } ``` -## example: sharding +### example: sharding ```rust @@ -176,6 +180,7 @@ pub fn process_place_order( pub fn check_instruction_version_and_load_data() { // this is newly added after the redeploy if access_as_unsigned(declare!("OldVersion111111111111111111111111111111111111"), READ).is_ok() { + // it seems that this transaction is construction by simulation with pre-redeploy program executable. return Err("we changed internal data loading implementation. to avoid unexpected malfunction retry"); } @@ -201,42 +206,42 @@ transaction: Bm9UhRBysjeT35ukzriheHKr76yiM1fPyEBMMw2yT9v1: {read: true, write: false} J8H1Gsvnm2CY5oVa1zw1LHHbfvtone8ZGsVBzjkkPbpy: {read: true, write: true} instructions: - accounts: [] + accesses: [] instruction_type: spl_token_transfer instructions: [...] accesses: [...] pre_balances/pre_token_balances post_balances/post_token_balances - token_approvals + token_token_approvals: ??? ``` also, page-indexed account can be incorporated to find compact combination of existing account indexes to match the required account list +## downside -## Other Proposals / alternative implementation - +race condition around program deploy (= possible account loading change) => just retry also seek to the ix versioning for perfection -# or customized entrypoint? +(traced program just load dummy addresses for tx versionsing for completeness) ## careful consideration -prevent program to be simulated or really-executed +prevent program detect to be simulated or really-executed -## downside -race condition around program deploy (= possible account loading change) => just retry -also, traced program just load dummy addresses for tx versionsing for completeness +## Other Proposals / alternative implementation + +### customized entrypoint? + +breaks compatibility? # Run these before replaying stage on validator unavoidable latency. (and scheduling difficulty). The proposed implementation doesn't have such a downside +# Future possible expansions - -# Future expansion - -Wallet account delta check -Browser-side bpf program simualtion for server-less architecture with online wasm translation +- Wallet account delta check +- Browser-side bpf program simualtion for server-less architecture with online wasm translation From ed92de0a8c30a9d517310aaf4c7810d5744cd8a5 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Tue, 8 Jun 2021 00:32:13 +0900 Subject: [PATCH 8/9] Tweak --- docs/src/proposals/traced-transaction-construction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index d4e57cf844b..97d06be303e 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -196,7 +196,7 @@ pub fn check_instruction_version_and_load_data() { `pre_balances` and `post_balances` needs to be updated? -sample return from simulatedTransaction: +### sample return from `simulateTransaction` (or define `traceTransaction` for the compatibility??): ```yml # these somewhat verbose formatting is for future expansion @@ -236,12 +236,12 @@ prevent program detect to be simulated or really-executed breaks compatibility? -# Run these before replaying stage on validator +### Run these before replaying stage on validator unavoidable latency. (and scheduling difficulty). The proposed implementation doesn't have such a downside # Future possible expansions -- Wallet account delta check +- Wallet account balance delta check? - Browser-side bpf program simualtion for server-less architecture with online wasm translation From 75516cc156c2396f787c365f4a0b0392f6a01cea Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Tue, 8 Jun 2021 00:39:55 +0900 Subject: [PATCH 9/9] Tweak --- docs/src/proposals/traced-transaction-construction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/proposals/traced-transaction-construction.md b/docs/src/proposals/traced-transaction-construction.md index 97d06be303e..148026d1a80 100644 --- a/docs/src/proposals/traced-transaction-construction.md +++ b/docs/src/proposals/traced-transaction-construction.md @@ -241,7 +241,7 @@ breaks compatibility? unavoidable latency. (and scheduling difficulty). The proposed implementation doesn't have such a downside -# Future possible expansions +## Future possible expansions -- Wallet account balance delta check? +- Wallet account balance delta check: append VerifyTokenBalances ix at last and pass the expected balances of spl-tokens or hash of it (also with delegation status). - Browser-side bpf program simualtion for server-less architecture with online wasm translation