Add programming faq (#12545)
* Add programming faq * feedback and new content * nudge
This commit is contained in:
		
							
								
								
									
										123
									
								
								docs/src/apps/programming-faq.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								docs/src/apps/programming-faq.md
									
									
									
									
									
										Normal file
									
								
							| @@ -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. | ||||
		Reference in New Issue
	
	Block a user