From 841e5e326c53060cf0067bdd429a12732b9e4cb7 Mon Sep 17 00:00:00 2001 From: Jack May Date: Mon, 8 Jul 2019 15:52:25 -0800 Subject: [PATCH] Program mutable lamports (#4964) --- programs/bpf/build.rs | 1 + programs/bpf/rust/external_spend/.gitignore | 3 +++ programs/bpf/rust/external_spend/Cargo.toml | 22 +++++++++++++++++++++ programs/bpf/rust/external_spend/Xargo.toml | 6 ++++++ programs/bpf/rust/external_spend/src/lib.rs | 21 ++++++++++++++++++++ programs/bpf/tests/programs.rs | 2 ++ sdk/bpf/rust/rust-utils/src/entrypoint.rs | 4 ++-- sdk/bpf/rust/rust-utils/src/log.rs | 2 +- 8 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 programs/bpf/rust/external_spend/.gitignore create mode 100644 programs/bpf/rust/external_spend/Cargo.toml create mode 100644 programs/bpf/rust/external_spend/Xargo.toml create mode 100644 programs/bpf/rust/external_spend/src/lib.rs diff --git a/programs/bpf/build.rs b/programs/bpf/build.rs index 62e47a4c81..b2e5176160 100644 --- a/programs/bpf/build.rs +++ b/programs/bpf/build.rs @@ -73,6 +73,7 @@ fn main() { "dep_crate", "iter", "many_args", + "external_spend", "noop", "panic", "tick_height", diff --git a/programs/bpf/rust/external_spend/.gitignore b/programs/bpf/rust/external_spend/.gitignore new file mode 100644 index 0000000000..e13de17f65 --- /dev/null +++ b/programs/bpf/rust/external_spend/.gitignore @@ -0,0 +1,3 @@ +/target/ + +Cargo.lock diff --git a/programs/bpf/rust/external_spend/Cargo.toml b/programs/bpf/rust/external_spend/Cargo.toml new file mode 100644 index 0000000000..89e1ef9162 --- /dev/null +++ b/programs/bpf/rust/external_spend/Cargo.toml @@ -0,0 +1,22 @@ + +# Note: This crate must be built using build.sh + +[package] +name = "solana-bpf-rust-external-spend" +version = "0.17.0" +description = "Solana BPF external spend program written in Rust" +authors = ["Solana Maintainers "] +repository = "https://github.com/solana-labs/solana" +license = "Apache-2.0" +homepage = "https://solana.com/" +edition = "2018" + +[dependencies] +solana-sdk-bpf-utils = { path = "../../../../sdk/bpf/rust/rust-utils", version = "0.17.0" } + +[workspace] +members = [] + +[lib] +crate-type = ["cdylib"] +name = "solana_bpf_rust_external_spend" diff --git a/programs/bpf/rust/external_spend/Xargo.toml b/programs/bpf/rust/external_spend/Xargo.toml new file mode 100644 index 0000000000..385a264b04 --- /dev/null +++ b/programs/bpf/rust/external_spend/Xargo.toml @@ -0,0 +1,6 @@ +[dependencies.compiler_builtins] +path = "../../../../sdk/bpf/dependencies/rust-bpf-sysroot/src/compiler-builtins" +features = ["c", "mem"] + +[target.bpfel-unknown-unknown.dependencies] +alloc = { path = "../../../../sdk/bpf/dependencies/rust-bpf-sysroot/src/liballoc" } \ No newline at end of file diff --git a/programs/bpf/rust/external_spend/src/lib.rs b/programs/bpf/rust/external_spend/src/lib.rs new file mode 100644 index 0000000000..4b49498b99 --- /dev/null +++ b/programs/bpf/rust/external_spend/src/lib.rs @@ -0,0 +1,21 @@ +//! @brief Example Rust-based BPF program that moves a lamport from one account to another + +#![no_std] +#![allow(unreachable_code)] +#![allow(unused_attributes)] + +extern crate solana_sdk_bpf_utils; + +use solana_sdk_bpf_utils::entrypoint::*; +use solana_sdk_bpf_utils::{entrypoint, info}; + +entrypoint!(process_instruction); +fn process_instruction(ka: &mut [SolKeyedAccount], _info: &SolClusterInfo, _data: &[u8]) -> bool { + // account 0 is the mint and not owned by this program, any debit of its lamports + // should result in a failed program execution. Test to ensure that this debit + // is seen by the runtime and fails as expected + *ka[0].lamports -= 1; + + info!("Success"); + true +} diff --git a/programs/bpf/tests/programs.rs b/programs/bpf/tests/programs.rs index 2a21953937..2c4bed4ece 100644 --- a/programs/bpf/tests/programs.rs +++ b/programs/bpf/tests/programs.rs @@ -94,6 +94,7 @@ mod bpf { ("solana_bpf_rust_dep_crate", true), ("solana_bpf_rust_iter", true), // ("solana_bpf_rust_many_args", true), // Issue #3099 + ("solana_bpf_rust_external_spend", false), ("solana_bpf_rust_noop", true), ("solana_bpf_rust_panic", false), ]; @@ -110,6 +111,7 @@ mod bpf { .. } = create_genesis_block(50); let bank = Bank::new(&genesis_block); + // register some ticks, used by solana_bpf_rust_tick_height for i in 0..10 { bank.register_tick(&hash::hash(format!("hashing {}", i).as_bytes())); diff --git a/sdk/bpf/rust/rust-utils/src/entrypoint.rs b/sdk/bpf/rust/rust-utils/src/entrypoint.rs index 41407b0e80..3ae78de769 100644 --- a/sdk/bpf/rust/rust-utils/src/entrypoint.rs +++ b/sdk/bpf/rust/rust-utils/src/entrypoint.rs @@ -15,7 +15,7 @@ pub struct SolKeyedAccount<'a> { /// Public key of the account pub is_signer: bool, /// Number of lamports owned by this account - pub lamports: u64, + pub lamports: &'a mut u64, /// On-chain data within this account pub data: &'a mut [u8], /// Program that owns this account @@ -79,7 +79,7 @@ pub unsafe fn deserialize<'a>( offset += size_of::(); #[allow(clippy::cast_ptr_alignment)] - let lamports = *(input.add(offset) as *const u64); + let lamports = &mut *(input.add(offset) as *mut u64); offset += size_of::(); #[allow(clippy::cast_ptr_alignment)] diff --git a/sdk/bpf/rust/rust-utils/src/log.rs b/sdk/bpf/rust/rust-utils/src/log.rs index 71315b9fc2..05dcb9f02f 100644 --- a/sdk/bpf/rust/rust-utils/src/log.rs +++ b/sdk/bpf/rust/rust-utils/src/log.rs @@ -82,7 +82,7 @@ pub fn sol_log_params(ka: &[SolKeyedAccount], data: &[u8]) { sol_log("- Key"); sol_log_key(&k.key); sol_log("- Lamports"); - sol_log_64(0, 0, 0, 0, k.lamports); + sol_log_64(0, 0, 0, 0, *k.lamports); sol_log("- AccountData"); sol_log_slice(k.data); sol_log("- Owner");