From b51c0f3095ab07c456298164a34f9f8e11fdc430 Mon Sep 17 00:00:00 2001 From: Jack May Date: Tue, 29 Sep 2020 09:06:54 -0700 Subject: [PATCH] Add programming faq (#12545) * Add programming faq * feedback and new content * nudge --- docs/src/apps/programming-faq.md | 123 +++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docs/src/apps/programming-faq.md diff --git a/docs/src/apps/programming-faq.md b/docs/src/apps/programming-faq.md new file mode 100644 index 000000000..5aa521bd9 --- /dev/null +++ b/docs/src/apps/programming-faq.md @@ -0,0 +1,123 @@ +--- +title: "Programming FAQ" +--- + +When writing or interacting with Solana programs, there are common questions or +challenges that often come up. Below are resources to help answer these +questions. If not addressed here, the Solana +[#developers](https://discord.gg/RxeGBH) Discord channel is a great resource. + +## CallDepth + +Cross-program invocations allow programs to invoke other programs directly but +the depth is constrained currently to 1. + +## CallDepthExceeded + +Programs are constrained to run quickly, and to facilitate this, the program's +call stack is limited to max depth. If this error is encountered, then the +program itself or its dependent crate packages have exceeded the max stack +depth. + +## Computational constraints + +To prevent a program from abusing computation resources, a cap is enforced +during execution. The following operations incur a cost: +- Executing BPF instructions +- Calling system calls (logging, creating program addresses, ...) +- Cross-program invocations incur a base cost and the cost of the program + invoked. + +## Failure to compiler due to `rand` incompatibility + +Programs are constrained to run deterministically, so random numbers are not +available. Sometimes a program may depend on a crate that depends itself on +`rand` even if the program does not use any of the random number functionality. +If a program depends on `rand`, the compilation will fail because there is not +`get-random` support for Solana. To work around this dependency issue, add the +following dependency to the program's `Cargo.toml`: + +``` +getrandom = { version = "0.1.14", features = ["dummy"] } +``` + +## Float Rust types + +Programs support a limited subset of Rust's float operations, though they +are highly discouraged due to the overhead involved. If a program attempts to +use a float operation that is not supported, the runtime will report an +unresolved symbol error. Be sure to include integration tests against a local +cluster to ensure the operation is supported. + +## Heap size + +Programs have access to a heap either directly in C or via the Rust `alloc` +APIs. To facilitate fast allocations, a simple 32KB bump heap is utilized. The +heap does not support `free` or `realloc` so use it wisely. + +## InvalidAccountData + +This program error can happen for a lot of reasons. Usually, it's caused by +passing an account to the program that the program is not expecting, either in +the wrong position in the instruction or an account not compatible with the +instruction being executed. + +An implementation of a program might also cause this error when performing a +cross-program instruction and forgetting to provide the account for the program +that you are calling. + +## InvalidInstructionData + +This program error can occur while trying to deserialize the instruction, check +that the structure passed in matches exactly the instruction. There may be some +padding between fields. If the program implements the Rust `Pack` trait then ry +packing and unpacking the instruction type `T` to determine the exact encoding +the program expects: + +https://github.com/solana-labs/solana/blob/master/sdk/src/program_pack.rs + + +## MissingRequiredSignature + +Some instructions require the account to be a signer; this error is returned if +an account expected to be signed is not. + +An implementation of a program might also cause this error when performing a +cross-program invocation that requires a signed program address, but the passed +signer seeds passed to `invoke_signed` don't match the signer seeds used to +create the program address (`create_program_address`). + +## Rust restrictions + +There are some Rust limitations since programs run in a resource-constrained, +single-threaded environment, and must be deterministic: + +- No access to + - std::fs + - std::net + - std::os + - std::future + - std::net + - std::process + - std::sync + - std::task + - std::thread + - std::time +- Limited access to: + - std::os + - rand or any crates that depend on it +- Bincode is extremely computationally expensive in both cycles and call depth and should be avoided +- String formatting should be avoided since it is also computational expensive +- No support for `println!`, `print!`, the Solana SDK helpers in `src/log.rs` + should be used instead + +## Stack size + +Solana programs compile down to Berkley Packet Filter instructions, which use +stack frames instead of a variable stack pointer. Each stack frame is limited +to 4KB. If a program violates that stack frame size, the compiler will report +the overrun as a warning. The reason a warning is reported rather than an error +is because some dependent crates may include functionality that violates the +stack frame restrictions even if the program doesn't use that functionality. If +the program violates the stack size at runtime, an `AccessViolation` error will +be reported.