124 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| 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.
 |