Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0e8f7c3
finalize token-extensions support in spl-gov
crypt0miester Jan 11, 2025
1c5cad9
finalize versioned transactions
crypt0miester Jan 12, 2025
4ed0b15
fix max buffer size
crypt0miester Feb 10, 2025
d07b7c1
remove unwrap() and add mathematicaloverflow error, fix comment in tests
crypt0miester Feb 12, 2025
6523f36
remove smallvec dependency
crypt0miester Apr 9, 2025
4475a7c
small typo fix
crypt0miester Apr 27, 2025
889d5b2
fix lookuptable checks
crypt0miester Apr 27, 2025
bf98767
fix discriminator check.
crypt0miester May 23, 2025
e1a2b90
remove unnecessary rent_sysvar_account
crypt0miester May 23, 2025
18459e9
fix typos and logs to explain the errors
crypt0miester May 23, 2025
18c5da5
fix deposit amount calculation
crypt0miester May 23, 2025
03e8fbf
transaction buffer creator must sign fix
crypt0miester May 23, 2025
03dfd11
transaction buffer creator/payer must sign for all of its actions
crypt0miester May 23, 2025
4637cfa
remove redundant max buffer size check
crypt0miester May 23, 2025
6d621ff
fix deprecated instructions
crypt0miester May 23, 2025
a4118bd
fix deprecated instructions (cleanup)
crypt0miester May 23, 2025
48d579c
fix account index range check
crypt0miester May 23, 2025
b12dec3
fix cargo tests and add comments to legacy pda derivation
crypt0miester May 24, 2025
ba024a4
cargo fmt
crypt0miester May 24, 2025
5141609
enable different community mint and council mint standard on create_r…
crypt0miester May 25, 2025
8f3a0c7
add payer_info and beneficiary_info checks
crypt0miester May 25, 2025
46dcd04
Merge branch 'versioned-transactions-2' into versioned-transactions
crypt0miester May 26, 2025
6aac97a
add a lookuptable slot extended check
crypt0miester May 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
472 changes: 424 additions & 48 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ resolver = "2"
solana-program = "2.1.7"
borsh = "1.5.1"
spl-token-2022 = { version = "6.0.0", features = ["no-entrypoint"] }
spl-transfer-hook-interface = { version = "0.8.2" }
solana-program-test = "2.1.7"
solana-sdk = "2.1.7"
solana-account-decoder = "2.1.7"
Expand All @@ -95,3 +94,14 @@ solana-banks-interface = "2.1.7"
solana-rpc-client = "2.1.7"
solana-rpc-client-api = "2.1.7"
solana-zk-token-sdk = "2.1.7"
spl-tlv-account-resolution = "0.9.0"
spl-transfer-hook-interface = "0.9.0"
spl-token-client = "0.13.0"


[workspace.lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(target_os, values("solana"))',
'cfg(feature, values("frozen-abi", "no-entrypoint"))',
]
6 changes: 6 additions & 0 deletions governance/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# SPL Governance Changelog

## v3.1.2 -

- Add deprecated warning for create_mint_governance() and create_token_governance() (it will be removed in v4.0.0)
- Add SPL Token 2022 support
- Add VersionedTransaction support for proposals

## v3.1.1 - 25 Apr 2022

- Weighted multi choice voting
Expand Down
3 changes: 3 additions & 0 deletions governance/addin-mock/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ spl-governance-test-sdk = { version = "0.1.3", path ="../../test-sdk"}

[lib]
crate-type = ["cdylib", "lib"]

[lints]
workspace = true
12 changes: 11 additions & 1 deletion governance/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ license = "Apache-2.0"
edition = "2021"

[features]
default = ["custom-heap"]
custom-heap = []
no-entrypoint = []
test-sbf = []
custom-panic = []

[dependencies]
arrayref = "0.3.7"
Expand All @@ -20,7 +23,8 @@ num-traits = "0.2"
serde = "1.0.195"
serde_derive = "1.0.103"
solana-program = { workspace = true }
spl-token = { version = "4.0.0", path = "../../token/program", features = ["no-entrypoint"] }
spl-token-2022 = { workspace = true }
spl-transfer-hook-interface = { workspace = true }
spl-governance-tools = { version = "0.1.3", path ="../tools"}
spl-governance-addin-api = { version = "0.1.3", path ="../addin-api"}
thiserror = "1.0"
Expand All @@ -33,6 +37,12 @@ solana-program-test = { workspace = true }
solana-sdk = { workspace = true }
spl-governance-test-sdk = { version = "0.1.3", path ="../test-sdk"}
spl-governance-addin-mock = { version = "0.1.3", path ="../addin-mock/program"}
spl-transfer-hook-example = { path = "../../token/transfer-hook/example", features = [
"no-entrypoint",
] }

[lib]
crate-type = ["cdylib", "lib"]

[lints]
workspace = true
144 changes: 141 additions & 3 deletions governance/program/src/entrypoint.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Program entrypoint definitions
#![cfg(all(target_os = "solana", not(feature = "no-entrypoint")))]
#![cfg(not(feature = "no-entrypoint"))]

use {
crate::{error::GovernanceError, processor},
Expand All @@ -9,10 +9,148 @@ use {
},
};

/*
Optimizing Bump Heap Allocation

Objective: Increase available heap memory while maintaining flexibility in program invocation.

1. Initial State: Default 32 KiB Heap

Memory Layout:
0x300000000 0x300008000
| |
v v
[--------------------]
^ ^
| |
VM Lower VM Upper
Boundary Boundary

Default Allocator (Allocates Backwards / Top Down) (Default 32 KiB):
0x300000000 0x300008000
| |
[--------------------]
^
|
Allocation starts here (SAFE)

2. Naive Approach: Increase HEAP_LENGTH to 8 * 32 KiB + Default Allocator

Memory Layout with Increased HEAP_LENGTH:
0x300000000 0x300008000 0x300040000
| | |
v v v
[--------------------|------------------------------------|]
^ ^ ^
| | |
VM Lower VM Upper Allocation starts here
Boundary Boundary (ACCESS VIOLATION!)

Issue: Access violation occurs without requestHeapFrame, requiring it for every transaction.

3. Optimized Solution: Forward Allocation with Flexible Heap Usage

Memory Layout (Same as Naive Approach):
0x300000000 0x300008000 0x300040000
| | |
v v v
[--------------------|------------------------------------|]
^ ^ ^
| | |
VM Lower VM Upper Allocator & VM
Boundary Boundary Heap Limit

Forward Allocator Behavior:

a) Without requestHeapFrame:
0x300000000 0x300008000
| |
[--------------------]
^ ^
| |
VM Lower VM Upper
Boundary Boundary
Allocation
starts here (SAFE)

b) With requestHeapFrame:
0x300000000 0x300008000 0x300040000
| | |
[--------------------|------------------------------------|]
^ ^ ^
| | |
VM Lower | VM Upper
Boundary Boundary
Allocation Allocation continues Maximum allocation
starts here with requestHeapFrame with requestHeapFrame
(SAFE)

Key Advantages:
1. Compatibility: Functions without requestHeapFrame for allocations ≤32 KiB.
2. Extensibility: Supports larger allocations when requestHeapFrame is invoked.
3. Efficiency: Eliminates mandatory requestHeapFrame calls for all transactions.

Conclusion:
The forward allocation strategy offers a robust solution, providing both backward
compatibility for smaller heap requirements and the flexibility to utilize extended
heap space when necessary.

The following allocator is a copy of the bump allocator found in
solana_program::entrypoint and
https://github.com/solana-labs/solana-program-library/blob/master/examples/rust/custom-heap/src/entrypoint.rs

but with changes to its HEAP_LENGTH and its
starting allocation address.
*/

#[cfg(target_os = "solana")]
use {
solana_program::entrypoint::HEAP_START_ADDRESS,
std::{alloc::Layout, mem::size_of, ptr::null_mut, usize},
};

/// Length of the memory region used for program heap.
pub const HEAP_LENGTH: usize = 8 * 32 * 1024;

#[cfg(target_os = "solana")]
struct BumpAllocator;

#[cfg(target_os = "solana")]
unsafe impl std::alloc::GlobalAlloc for BumpAllocator {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
const POS_PTR: *mut usize = HEAP_START_ADDRESS as *mut usize;
const TOP_ADDRESS: usize = HEAP_START_ADDRESS as usize + HEAP_LENGTH;
const BOTTOM_ADDRESS: usize = HEAP_START_ADDRESS as usize + size_of::<*mut u8>();
let mut pos = *POS_PTR;
if pos == 0 {
// First time, set starting position to bottom address
pos = BOTTOM_ADDRESS;
}
// Align the position upwards
pos = (pos + layout.align() - 1) & !(layout.align() - 1);
let next_pos = pos.saturating_add(layout.size());
if next_pos > TOP_ADDRESS {
return null_mut();
}
*POS_PTR = next_pos;
pos as *mut u8
}

#[inline]
unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
// I'm a bump allocator, I don't free
}
}

#[cfg(target_os = "solana")]
#[global_allocator]
static A: BumpAllocator = BumpAllocator;

solana_program::entrypoint!(process_instruction);
fn process_instruction(
fn process_instruction<'a>(
program_id: &Pubkey,
accounts: &[AccountInfo],
accounts: &'a [AccountInfo<'a>],
instruction_data: &[u8],
) -> ProgramResult {
if let Err(error) = processor::process_instruction(program_id, accounts, instruction_data) {
Expand Down
104 changes: 98 additions & 6 deletions governance/program/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ pub enum GovernanceError {
#[error("Governing Token Owner must sign transaction")]
GoverningTokenOwnerMustSign,

/// Governing Token Owner or Delegate must sign transaction
#[error("Governing Token Owner or Delegate must sign transaction")]
/// Governing Token Owner or Delegate must sign transaction
#[error("Governing Token Owner or Delegate must sign transaction")]
GoverningTokenOwnerOrDelegateMustSign, // 505

/// All votes must be relinquished to withdraw governing tokens
Expand Down Expand Up @@ -507,19 +507,111 @@ pub enum GovernanceError {

/// Invalid Governance for RequiredSignatory
#[error("Invalid Governance for RequiredSignatory")]
InvalidGovernanceForRequiredSignatory,
InvalidGovernanceForRequiredSignatory, // 621

/// SignatoryRecord already exists
#[error("Signatory Record has already been created")]
SignatoryRecordAlreadyExists,
SignatoryRecordAlreadyExists, // 622

/// Instruction has been removed
#[error("Instruction has been removed")]
InstructionDeprecated,
InstructionDeprecated, // 623

/// Proposal is missing signatories required by its governance
#[error("Proposal is missing required signatories")]
MissingRequiredSignatories,
MissingRequiredSignatories, // 624

/// Math Overflow
#[error("Mathematical Overflow")]
MathematicalOverflow, // 625

/// Invalid lookup table account owner
#[error("Invalid lookup table account owner")]
InvalidLookupTableAccountOwner, // 626

/// Invalid lookup table accounts key
#[error("Invalid lookup table account key")]
InvalidLookupTableAccountKey, // 627

/// Invalid number of accounts in message
#[error("Invalid number of accounts in message")]
InvalidNumberOfAccountsInMessage, // 628

/// Invalid account found in message
#[error("Invalid account found in message")]
InvalidAccountFoundInMessage, // 629

/// Invalid account signer found in message
#[error("Invalid account signer found in message")]
InvalidAccountSigner, // 630

/// Invalid writable account found in message
#[error("Invalid writable account found in message")]
InvalidAccountWritable, // 631

/// Invalid account found
#[error("Invalid account found")]
InvalidAccountFound, // 632

/// Account in lookuptable is missing
#[error("Account in lookuptable is missing")]
MissingAddressInLookuptable, // 633

/// Account is protected, it cannot be passed into a CPI as writable
#[error("Account is protected, it cannot be passed into a CPI as writable")]
ProtectedAccount, // 634

/// TransactionMessage is malformed
#[error("TransactionMessage is malformed")]
InvalidTransactionMessage, // 635

/// Transaction buffer already exists
#[error("Transaction buffer already exists")]
TransactionBufferAlreadyExists, // 636

/// Versioned Transaction already exists
#[error("Versioned Transaction already exists")]
VersionedTransactionAlreadyExists, // 637

/// Transaction buffer unauthorized extension
#[error("Transaction buffer unauthorized extension")]
TransactionBufferUnauthorizedExtension, // 638

/// Versioned Transaction already removed
#[error("Versioned Transaction already removed")]
VersionedTransactionAlreadyRemoved, // 639

/// Final buffer exceeded 10128 bytes
#[error("Final buffer exceeded 10128 bytes")]
FinalBufferSizeExceeded, // 640

/// Final message buffer hash doesnt match the expected hash
#[error("Final message buffer hash doesnt match the expected hash")]
FinalBufferHashMismatch, // 641

/// Final buffer size mismatch
#[error("Final buffer size mismatch")]
FinalBufferSizeMismatch, // 642

/// Invalid number of accounts in the address look up table account
#[error("Invalid number of accounts in the address look up table account")]
InvalidNumberOfAccounts, // 643

/// Transaction buffer does not exist
#[error("Transaction buffer does not exist")]
TransactionBufferDoesNotExist, // 644

/// Invalid account type
#[error("Invalid account type")]
InvalidAccountType, // 645

/// Transaction creator must sign
#[error("Transaction creator must sign")]
TransactionCreatorMustSign, // 646

/// Lookup Table Account has been extended after vote has started
#[error("Lookup Table Account has been extended after vote has started")]
LookupTableAccountHasBeenAltered, // 647
}

impl PrintProgramError for GovernanceError {
Expand Down
Loading
Loading