feat(sbf): Add Poseidon syscall (#32680)
Computing Poseidon[0] hashes is too expensive to be done in a Solana program in one transaction. Poseidon is a zero-knowlege proof friendly hash function, used by the majority of ZK-based projects, including the ones built on top of Solana. This change introduces the `sol_poseidon` syscall which takes 2D byte slice as an input and then calculates a Poseidon hash using a BN254 curve and the following Poseidon parameters: * x^5 S-boxes * width - 2 ≤ t ≤ 13 * inputs - 1 ≤ n ≤ 12 * 8 full rounds and partial rounds depending on t: [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65] Computation of Poseidon hashes is done with the light-poseidon[1] crate, which is audited[2] and compatible with Circom[3] (BN254 curve, the same parameters and constants). Proposed compute costs depend on number of inputs and are based on light-poseidon benchmarks[4]. [0] https://www.poseidon-hash.info/ [1] https://crates.io/crates/light-poseidon [2] https://github.com/Lightprotocol/light-poseidon/blob/main/assets/audit.pdf [3] https://docs.circom.io/ [4] https://github.com/Lightprotocol/light-poseidon/tree/main#performance
This commit is contained in:
parent
01dbe4970c
commit
e6dc3dac45
|
@ -2963,6 +2963,17 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "light-poseidon"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "949bdd22e4ed93481d45e9a6badb34b99132bcad0c8a8d4f05c42f7dcc7b90bc"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-ff",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
|
@ -6478,6 +6489,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libc",
|
||||
"libsecp256k1",
|
||||
"light-poseidon",
|
||||
"log",
|
||||
"memoffset 0.9.0",
|
||||
"num-bigint 0.4.4",
|
||||
|
|
|
@ -227,6 +227,7 @@ lazy_static = "1.4.0"
|
|||
libc = "0.2.147"
|
||||
libloading = "0.7.4"
|
||||
libsecp256k1 = "0.6.0"
|
||||
light-poseidon = "0.1.1"
|
||||
log = "0.4.20"
|
||||
lru = "0.7.7"
|
||||
lz4 = "1.24.0"
|
||||
|
|
|
@ -122,6 +122,14 @@ pub struct ComputeBudget {
|
|||
/// Maximum accounts data size, in bytes, that a transaction is allowed to load; The
|
||||
/// value is capped by MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES to prevent overuse of memory.
|
||||
pub loaded_accounts_data_size_limit: usize,
|
||||
/// Coefficient `a` of the quadratic function which determines the number
|
||||
/// of compute units consumed to call poseidon syscall for a given number
|
||||
/// of inputs.
|
||||
pub poseidon_cost_coefficient_a: u64,
|
||||
/// Coefficient `c` of the quadratic function which determines the number
|
||||
/// of compute units consumed to call poseidon syscall for a given number
|
||||
/// of inputs.
|
||||
pub poseidon_cost_coefficient_c: u64,
|
||||
}
|
||||
|
||||
impl Default for ComputeBudget {
|
||||
|
@ -171,6 +179,8 @@ impl ComputeBudget {
|
|||
alt_bn128_pairing_one_pair_cost_other: 12_121,
|
||||
big_modular_exponentiation_cost: 33,
|
||||
loaded_accounts_data_size_limit: MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES,
|
||||
poseidon_cost_coefficient_a: 61,
|
||||
poseidon_cost_coefficient_c: 542,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,6 +318,35 @@ impl ComputeBudget {
|
|||
prioritization_fee: prioritization_fee_details.get_fee(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns cost of the Poseidon hash function for the given number of
|
||||
/// inputs is determined by the following quadratic function:
|
||||
///
|
||||
/// 61*n^2 + 542
|
||||
///
|
||||
/// Which aproximates the results of benchmarks of light-posiedon
|
||||
/// library[0]. These results assume 1 CU per 33 ns. Examples:
|
||||
///
|
||||
/// * 1 input
|
||||
/// * light-poseidon benchmark: `18,303 / 33 ≈ 555`
|
||||
/// * function: `61*1^2 + 542 = 603`
|
||||
/// * 2 inputs
|
||||
/// * light-poseidon benchmark: `25,866 / 33 ≈ 784`
|
||||
/// * function: `61*2^2 + 542 = 786`
|
||||
/// * 3 inputs
|
||||
/// * light-poseidon benchmark: `37,549 / 33 ≈ 1,138`
|
||||
/// * function; `61*3^2 + 542 = 1091`
|
||||
///
|
||||
/// [0] https://github.com/Lightprotocol/light-poseidon#performance
|
||||
pub fn poseidon_cost(&self, nr_inputs: u64) -> Option<u64> {
|
||||
let squared_inputs = nr_inputs.checked_pow(2)?;
|
||||
let mul_result = self
|
||||
.poseidon_cost_coefficient_a
|
||||
.checked_mul(squared_inputs)?;
|
||||
let final_result = mul_result.checked_add(self.poseidon_cost_coefficient_c)?;
|
||||
|
||||
Some(final_result)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -37,8 +37,8 @@ use {
|
|||
disable_cpi_setting_executable_and_rent_epoch, disable_deploy_of_alloc_free_syscall,
|
||||
disable_fees_sysvar, enable_alt_bn128_syscall, enable_big_mod_exp_syscall,
|
||||
enable_early_verification_of_account_modifications, enable_partitioned_epoch_reward,
|
||||
error_on_syscall_bpf_function_hash_collisions, last_restart_slot_sysvar,
|
||||
libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
||||
enable_poseidon_syscall, error_on_syscall_bpf_function_hash_collisions,
|
||||
last_restart_slot_sysvar, libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
||||
stop_sibling_instruction_search_at_parent, stop_truncating_strings_in_syscalls,
|
||||
switch_to_new_elf_parser,
|
||||
},
|
||||
|
@ -47,7 +47,7 @@ use {
|
|||
AccountMeta, InstructionError, ProcessedSiblingInstruction,
|
||||
TRANSACTION_LEVEL_STACK_HEIGHT,
|
||||
},
|
||||
keccak, native_loader,
|
||||
keccak, native_loader, poseidon,
|
||||
precompiles::is_precompile,
|
||||
program::MAX_RETURN_DATA,
|
||||
program_stubs::is_nonoverlapping,
|
||||
|
@ -125,6 +125,8 @@ pub enum SyscallError {
|
|||
InvalidAttribute,
|
||||
#[error("Invalid pointer")]
|
||||
InvalidPointer,
|
||||
#[error("Arithmetic overflow")]
|
||||
ArithmeticOverflow,
|
||||
}
|
||||
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
|
@ -160,6 +162,7 @@ pub fn create_program_runtime_environment_v1<'a>(
|
|||
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
|
||||
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
|
||||
let last_restart_slot_syscall_enabled = feature_set.is_active(&last_restart_slot_sysvar::id());
|
||||
let enable_poseidon_syscall = feature_set.is_active(&enable_poseidon_syscall::id());
|
||||
// !!! ATTENTION !!!
|
||||
// When adding new features for RBPF here,
|
||||
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
|
||||
|
@ -327,6 +330,14 @@ pub fn create_program_runtime_environment_v1<'a>(
|
|||
SyscallBigModExp::call,
|
||||
)?;
|
||||
|
||||
// Poseidon
|
||||
register_feature_gated_function!(
|
||||
result,
|
||||
enable_poseidon_syscall,
|
||||
b"sol_poseidon",
|
||||
SyscallPoseidon::call,
|
||||
)?;
|
||||
|
||||
// Log data
|
||||
result.register_function(b"sol_log_data", SyscallLogData::call)?;
|
||||
|
||||
|
@ -1795,6 +1806,78 @@ declare_syscall!(
|
|||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
// Poseidon
|
||||
SyscallPoseidon,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
parameters: u64,
|
||||
endianness: u64,
|
||||
vals_addr: u64,
|
||||
vals_len: u64,
|
||||
result_addr: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
) -> Result<u64, Error> {
|
||||
let parameters: poseidon::Parameters = parameters.try_into()?;
|
||||
let endianness: poseidon::Endianness = endianness.try_into()?;
|
||||
|
||||
if vals_len > 12 {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Poseidon hashing {} sequences is not supported",
|
||||
vals_len,
|
||||
);
|
||||
return Err(SyscallError::InvalidLength.into());
|
||||
}
|
||||
|
||||
let budget = invoke_context.get_compute_budget();
|
||||
let Some(cost) = budget.poseidon_cost(vals_len) else {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
"Overflow while calculating the compute cost"
|
||||
);
|
||||
return Err(SyscallError::ArithmeticOverflow.into());
|
||||
};
|
||||
consume_compute_meter(invoke_context, cost.to_owned())?;
|
||||
|
||||
let hash_result = translate_slice_mut::<u8>(
|
||||
memory_mapping,
|
||||
result_addr,
|
||||
poseidon::HASH_BYTES as u64,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
let inputs = translate_slice::<&[u8]>(
|
||||
memory_mapping,
|
||||
vals_addr,
|
||||
vals_len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
let inputs = inputs
|
||||
.iter()
|
||||
.map(|input| {
|
||||
translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
input.as_ptr() as *const _ as u64,
|
||||
input.len() as u64,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, Error>>()?;
|
||||
let hash = match poseidon::hashv(parameters, endianness, inputs.as_slice()) {
|
||||
Ok(hash) => hash,
|
||||
Err(e) => {
|
||||
return Ok(e.into());
|
||||
}
|
||||
};
|
||||
hash_result.copy_from_slice(&hash.to_bytes());
|
||||
|
||||
Ok(SUCCESS)
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
|
|
|
@ -2603,6 +2603,17 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "light-poseidon"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "949bdd22e4ed93481d45e9a6badb34b99132bcad0c8a8d4f05c42f7dcc7b90bc"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-ff",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
|
@ -5248,6 +5259,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libc",
|
||||
"libsecp256k1 0.6.0",
|
||||
"light-poseidon",
|
||||
"log",
|
||||
"memoffset 0.9.0",
|
||||
"num-bigint 0.4.4",
|
||||
|
@ -5848,6 +5860,14 @@ dependencies = [
|
|||
"solana-program",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-sbf-rust-poseidon"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"array-bytes",
|
||||
"solana-program",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-sbf-rust-rand"
|
||||
version = "1.17.0"
|
||||
|
|
|
@ -140,6 +140,7 @@ members = [
|
|||
"rust/panic",
|
||||
"rust/param_passing",
|
||||
"rust/param_passing_dep",
|
||||
"rust/poseidon",
|
||||
"rust/rand",
|
||||
"rust/realloc",
|
||||
"rust/realloc_invoke",
|
||||
|
|
|
@ -92,6 +92,7 @@ fn main() {
|
|||
"noop",
|
||||
"panic",
|
||||
"param_passing",
|
||||
"poseidon",
|
||||
"rand",
|
||||
"realloc",
|
||||
"realloc_invoke",
|
||||
|
|
|
@ -0,0 +1,359 @@
|
|||
/**
|
||||
* @brief Poseidon syscall test
|
||||
*/
|
||||
#include <sol/assert.h>
|
||||
#include <sol/poseidon.h>
|
||||
#include <sol/string.h>
|
||||
|
||||
extern uint64_t entrypoint(const uint8_t *input) {
|
||||
// Two inputs: ones and twos (big-endian).
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {13, 84, 225, 147, 143, 138, 140, 28, 125, 235, 94,
|
||||
3, 85, 242, 99, 25, 32, 123, 132, 254, 156, 162,
|
||||
206, 27, 38, 231, 53, 200, 41, 130, 25, 144};
|
||||
|
||||
uint8_t input1[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint8_t input2[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input2, SOL_ARRAY_SIZE(input2)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// Two inputs: ones and twos (little-endian).
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {144, 25, 130, 41, 200, 53, 231, 38, 27, 206, 162,
|
||||
156, 254, 132, 123, 32, 25, 99, 242, 85, 3, 94,
|
||||
235, 125, 28, 140, 138, 143, 147, 225, 84, 13};
|
||||
|
||||
uint8_t input1[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint8_t input2[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input2, SOL_ARRAY_SIZE(input2)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_LITTLE_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
|
||||
uint8_t input1[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
};
|
||||
|
||||
// 1 input.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
41, 23, 97, 0, 234, 169, 98, 189, 193, 254, 108,
|
||||
101, 77, 106, 60, 19, 14, 150, 164, 209, 22, 139,
|
||||
51, 132, 139, 137, 125, 197, 2, 130, 1, 51,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 2 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
0, 122, 243, 70, 226, 211, 4, 39, 158, 121, 224,
|
||||
169, 243, 2, 63, 119, 18, 148, 167, 138, 203, 112,
|
||||
231, 63, 144, 175, 226, 124, 173, 64, 30, 129,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 3 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
2, 192, 6, 110, 16, 167, 42, 189, 43, 51, 195,
|
||||
178, 20, 203, 62, 129, 188, 177, 182, 227, 9, 97,
|
||||
205, 35, 194, 2, 177, 134, 115, 191, 37, 67,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 4 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
8, 44, 156, 55, 10, 13, 36, 244, 65, 111, 188,
|
||||
65, 74, 55, 104, 31, 120, 68, 45, 39, 216, 99,
|
||||
133, 153, 28, 23, 214, 252, 12, 75, 125, 113,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 5 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
16, 56, 150, 5, 174, 104, 141, 79, 20, 219, 133,
|
||||
49, 34, 196, 125, 102, 168, 3, 199, 43, 65, 88,
|
||||
156, 177, 191, 134, 135, 65, 178, 6, 185, 187,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 6 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
42, 115, 246, 121, 50, 140, 62, 171, 114, 74, 163,
|
||||
229, 189, 191, 80, 179, 144, 53, 215, 114, 159, 19,
|
||||
91, 151, 9, 137, 15, 133, 197, 220, 94, 118,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 7 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
34, 118, 49, 10, 167, 243, 52, 58, 40, 66, 20,
|
||||
19, 157, 157, 169, 89, 190, 42, 49, 178, 199, 8,
|
||||
165, 248, 25, 84, 178, 101, 229, 58, 48, 184,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 8 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
23, 126, 20, 83, 196, 70, 225, 176, 125, 43, 66,
|
||||
51, 66, 81, 71, 9, 92, 79, 202, 187, 35, 61,
|
||||
35, 11, 109, 70, 162, 20, 217, 91, 40, 132,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 9 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
14, 143, 238, 47, 228, 157, 163, 15, 222, 235, 72,
|
||||
196, 46, 187, 68, 204, 110, 231, 5, 95, 97, 251,
|
||||
202, 94, 49, 59, 138, 95, 202, 131, 76, 71,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 10 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
46, 196, 198, 94, 99, 120, 171, 140, 115, 48, 133,
|
||||
79, 74, 112, 119, 193, 255, 146, 96, 228, 72, 133,
|
||||
196, 184, 29, 209, 49, 173, 58, 134, 205, 150,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 11 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
0, 113, 61, 65, 236, 166, 53, 241, 23, 212, 236,
|
||||
188, 235, 95, 58, 102, 220, 65, 66, 235, 112, 181,
|
||||
103, 101, 188, 53, 143, 27, 236, 64, 187, 155,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
// 12 inputs.
|
||||
{
|
||||
uint8_t result[POSEIDON_RESULT_LENGTH];
|
||||
uint8_t expected[] = {
|
||||
20, 57, 11, 224, 186, 239, 36, 155, 212, 124, 101,
|
||||
221, 172, 101, 194, 229, 46, 133, 19, 192, 129, 193,
|
||||
205, 114, 201, 128, 6, 9, 142, 154, 143, 190,
|
||||
};
|
||||
|
||||
const SolBytes inputs[] = {
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)},
|
||||
{input1, SOL_ARRAY_SIZE(input1)}, {input1, SOL_ARRAY_SIZE(input1)}};
|
||||
|
||||
sol_poseidon(
|
||||
POSEIDON_PARAMETERS_BN254_X5,
|
||||
POSEIDON_ENDIANNESS_BIG_ENDIAN,
|
||||
inputs,
|
||||
SOL_ARRAY_SIZE(inputs),
|
||||
result
|
||||
);
|
||||
|
||||
sol_assert(0 == sol_memcmp(result, expected, POSEIDON_RESULT_LENGTH));
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "solana-sbf-rust-poseidon"
|
||||
description = "Solana SBF test program written in Rust"
|
||||
version = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
homepage = { workspace = true }
|
||||
license = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
array-bytes = { workspace = true }
|
||||
solana-program = { workspace = true }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -0,0 +1,230 @@
|
|||
//! Example SBF program using Poseidon syscall
|
||||
|
||||
use solana_program::{
|
||||
custom_heap_default, custom_panic_default, msg,
|
||||
poseidon::{hashv, Endianness, Parameters, PoseidonSyscallError},
|
||||
};
|
||||
|
||||
fn test_poseidon_input_ones_twos() -> Result<(), PoseidonSyscallError> {
|
||||
let input1 = [1u8; 32];
|
||||
let input2 = [2u8; 32];
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input1, &input2],
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
13, 84, 225, 147, 143, 138, 140, 28, 125, 235, 94, 3, 85, 242, 99, 25, 32, 123, 132,
|
||||
254, 156, 162, 206, 27, 38, 231, 53, 200, 41, 130, 25, 144
|
||||
]
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::LittleEndian,
|
||||
&[&input1, &input2],
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
144, 25, 130, 41, 200, 53, 231, 38, 27, 206, 162, 156, 254, 132, 123, 32, 25, 99, 242,
|
||||
85, 3, 94, 235, 125, 28, 140, 138, 143, 147, 225, 84, 13
|
||||
],
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_poseidon_input_one() -> Result<(), PoseidonSyscallError> {
|
||||
let input = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1,
|
||||
];
|
||||
|
||||
let hash = hashv(Parameters::Bn254X5, Endianness::BigEndian, &[&input])?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
41, 23, 97, 0, 234, 169, 98, 189, 193, 254, 108, 101, 77, 106, 60, 19, 14, 150, 164,
|
||||
209, 22, 139, 51, 132, 139, 137, 125, 197, 2, 130, 1, 51,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
0, 122, 243, 70, 226, 211, 4, 39, 158, 121, 224, 169, 243, 2, 63, 119, 18, 148, 167,
|
||||
138, 203, 112, 231, 63, 144, 175, 226, 124, 173, 64, 30, 129,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
2, 192, 6, 110, 16, 167, 42, 189, 43, 51, 195, 178, 20, 203, 62, 129, 188, 177, 182,
|
||||
227, 9, 97, 205, 35, 194, 2, 177, 134, 115, 191, 37, 67,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input, &input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
8, 44, 156, 55, 10, 13, 36, 244, 65, 111, 188, 65, 74, 55, 104, 31, 120, 68, 45, 39,
|
||||
216, 99, 133, 153, 28, 23, 214, 252, 12, 75, 125, 113,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input, &input, &input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
16, 56, 150, 5, 174, 104, 141, 79, 20, 219, 133, 49, 34, 196, 125, 102, 168, 3, 199,
|
||||
43, 65, 88, 156, 177, 191, 134, 135, 65, 178, 6, 185, 187,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input, &input, &input, &input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
42, 115, 246, 121, 50, 140, 62, 171, 114, 74, 163, 229, 189, 191, 80, 179, 144, 53,
|
||||
215, 114, 159, 19, 91, 151, 9, 137, 15, 133, 197, 220, 94, 118,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input, &input, &input, &input, &input, &input, &input],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
34, 118, 49, 10, 167, 243, 52, 58, 40, 66, 20, 19, 157, 157, 169, 89, 190, 42, 49, 178,
|
||||
199, 8, 165, 248, 25, 84, 178, 101, 229, 58, 48, 184,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[
|
||||
&input, &input, &input, &input, &input, &input, &input, &input,
|
||||
],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
23, 126, 20, 83, 196, 70, 225, 176, 125, 43, 66, 51, 66, 81, 71, 9, 92, 79, 202, 187,
|
||||
35, 61, 35, 11, 109, 70, 162, 20, 217, 91, 40, 132,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[
|
||||
&input, &input, &input, &input, &input, &input, &input, &input, &input,
|
||||
],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
14, 143, 238, 47, 228, 157, 163, 15, 222, 235, 72, 196, 46, 187, 68, 204, 110, 231, 5,
|
||||
95, 97, 251, 202, 94, 49, 59, 138, 95, 202, 131, 76, 71,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[
|
||||
&input, &input, &input, &input, &input, &input, &input, &input, &input, &input,
|
||||
],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
46, 196, 198, 94, 99, 120, 171, 140, 115, 48, 133, 79, 74, 112, 119, 193, 255, 146, 96,
|
||||
228, 72, 133, 196, 184, 29, 209, 49, 173, 58, 134, 205, 150,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[
|
||||
&input, &input, &input, &input, &input, &input, &input, &input, &input, &input, &input,
|
||||
],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
0, 113, 61, 65, 236, 166, 53, 241, 23, 212, 236, 188, 235, 95, 58, 102, 220, 65, 66,
|
||||
235, 112, 181, 103, 101, 188, 53, 143, 27, 236, 64, 187, 155,
|
||||
],
|
||||
);
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[
|
||||
&input, &input, &input, &input, &input, &input, &input, &input, &input, &input, &input,
|
||||
&input,
|
||||
],
|
||||
)?;
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
20, 57, 11, 224, 186, 239, 36, 155, 212, 124, 101, 221, 172, 101, 194, 229, 46, 133,
|
||||
19, 192, 129, 193, 205, 114, 201, 128, 6, 9, 142, 154, 143, 190,
|
||||
],
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||
msg!("poseidon_hash");
|
||||
|
||||
if let Err(e) = test_poseidon_input_ones_twos() {
|
||||
return e.into();
|
||||
}
|
||||
if let Err(e) = test_poseidon_input_one() {
|
||||
return e.into();
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
custom_heap_default!();
|
||||
custom_panic_default!();
|
|
@ -285,6 +285,7 @@ fn test_program_sbf_sanity() {
|
|||
("noop", true),
|
||||
("noop++", true),
|
||||
("panic", false),
|
||||
("poseidon", true),
|
||||
("relative_call", true),
|
||||
("return_data", true),
|
||||
("sanity", true),
|
||||
|
@ -312,6 +313,7 @@ fn test_program_sbf_sanity() {
|
|||
("solana_sbf_rust_noop", true),
|
||||
("solana_sbf_rust_panic", false),
|
||||
("solana_sbf_rust_param_passing", true),
|
||||
("solana_sbf_rust_poseidon", true),
|
||||
("solana_sbf_rust_rand", true),
|
||||
("solana_sbf_rust_sanity", true),
|
||||
("solana_sbf_rust_secp256k1_recover", true),
|
||||
|
|
|
@ -58,6 +58,7 @@ curve25519-dalek = { workspace = true, features = ["serde"] }
|
|||
itertools = { workspace = true }
|
||||
libc = { workspace = true, features = ["extra_traits"] }
|
||||
libsecp256k1 = { workspace = true }
|
||||
light-poseidon = { workspace = true }
|
||||
num-bigint = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
tiny-bip39 = { workspace = true }
|
||||
|
|
|
@ -506,6 +506,7 @@ pub mod log;
|
|||
pub mod message;
|
||||
pub mod native_token;
|
||||
pub mod nonce;
|
||||
pub mod poseidon;
|
||||
pub mod program;
|
||||
pub mod program_error;
|
||||
pub mod program_memory;
|
||||
|
|
|
@ -0,0 +1,444 @@
|
|||
//! Hashing with the [Poseidon] hash function.
|
||||
//!
|
||||
//! [Poseidon]: https://www.poseidon-hash.info/
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Length of Poseidon hash result.
|
||||
pub const HASH_BYTES: usize = 32;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum PoseidonSyscallError {
|
||||
#[error("Invalid parameters.")]
|
||||
InvalidParameters,
|
||||
#[error("Invalid endianness.")]
|
||||
InvalidEndianness,
|
||||
#[error("Invalid number of inputs. Maximum allowed is 12.")]
|
||||
InvalidNumberOfInputs,
|
||||
#[error("Input is an empty slice.")]
|
||||
EmptyInput,
|
||||
#[error(
|
||||
"Invalid length of the input. The length matching the modulus of the prime field is 32."
|
||||
)]
|
||||
InvalidInputLength,
|
||||
#[error("Input is larger than the modulus of the prime field.")]
|
||||
InputLargerThanModulus,
|
||||
#[error("Failed to convert a vector of bytes into an array.")]
|
||||
VecToArray,
|
||||
#[error("Failed to convert the number of inputs from u64 to u8.")]
|
||||
U64Tou8,
|
||||
#[error("Invalid width. Choose a width between 2 and 16 for 1 to 15 inputs.")]
|
||||
InvalidWidthCircom,
|
||||
#[error("Unexpected error")]
|
||||
Unexpected,
|
||||
}
|
||||
|
||||
impl From<u64> for PoseidonSyscallError {
|
||||
fn from(error: u64) -> Self {
|
||||
match error {
|
||||
1 => PoseidonSyscallError::InvalidParameters,
|
||||
2 => PoseidonSyscallError::InvalidEndianness,
|
||||
3 => PoseidonSyscallError::InvalidNumberOfInputs,
|
||||
4 => PoseidonSyscallError::EmptyInput,
|
||||
5 => PoseidonSyscallError::InvalidInputLength,
|
||||
6 => PoseidonSyscallError::InputLargerThanModulus,
|
||||
7 => PoseidonSyscallError::VecToArray,
|
||||
8 => PoseidonSyscallError::U64Tou8,
|
||||
9 => PoseidonSyscallError::InvalidWidthCircom,
|
||||
_ => PoseidonSyscallError::Unexpected,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PoseidonSyscallError> for u64 {
|
||||
fn from(error: PoseidonSyscallError) -> Self {
|
||||
match error {
|
||||
PoseidonSyscallError::InvalidParameters => 1,
|
||||
PoseidonSyscallError::InvalidEndianness => 2,
|
||||
PoseidonSyscallError::InvalidNumberOfInputs => 3,
|
||||
PoseidonSyscallError::EmptyInput => 4,
|
||||
PoseidonSyscallError::InvalidInputLength => 5,
|
||||
PoseidonSyscallError::InputLargerThanModulus => 6,
|
||||
PoseidonSyscallError::VecToArray => 7,
|
||||
PoseidonSyscallError::U64Tou8 => 8,
|
||||
PoseidonSyscallError::InvalidWidthCircom => 9,
|
||||
PoseidonSyscallError::Unexpected => 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration parameters for the Poseidon hash function.
|
||||
///
|
||||
/// The parameters of each configuration consist of:
|
||||
///
|
||||
/// - **Elliptic curve type**: This defines the prime field in which the
|
||||
/// cryptographic operations are conducted.
|
||||
/// - **S-Box**: The substitution box used in the cryptographic rounds.
|
||||
/// - **Full rounds**: The number of full transformation rounds in the hash
|
||||
/// function.
|
||||
/// - **Partial rounds**: The number of partial transformation rounds in the
|
||||
/// hash function.
|
||||
///
|
||||
/// Each configuration variant's name is composed of its elliptic curve type
|
||||
/// followed by its S-Box specification.
|
||||
#[repr(u64)]
|
||||
pub enum Parameters {
|
||||
/// Configuration using the Barreto–Naehrig curve with an embedding degree
|
||||
/// of 12, defined over a 254-bit prime field.
|
||||
///
|
||||
/// Configuration Details:
|
||||
/// - **S-Box**: \( x^5 \)
|
||||
/// - **Width**: \( 2 \leq t \leq 13 \)
|
||||
/// - **Inputs**: \( 1 \leq n \leq 12 \)
|
||||
/// - **Full rounds**: 8
|
||||
/// - **Partial rounds**: Depending on width: [56, 57, 56, 60, 60, 63, 64,
|
||||
/// 63, 60, 66, 60, 65]
|
||||
Bn254X5 = 0,
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for Parameters {
|
||||
type Error = PoseidonSyscallError;
|
||||
|
||||
fn try_from(value: u64) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
x if x == Parameters::Bn254X5 as u64 => Ok(Parameters::Bn254X5),
|
||||
_ => Err(PoseidonSyscallError::InvalidParameters),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Parameters> for u64 {
|
||||
fn from(value: Parameters) -> Self {
|
||||
match value {
|
||||
Parameters::Bn254X5 => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Endianness of inputs and result.
|
||||
#[repr(u64)]
|
||||
pub enum Endianness {
|
||||
/// Big-endian inputs and result.
|
||||
BigEndian = 0,
|
||||
/// Little-endian inputs and result.
|
||||
LittleEndian,
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for Endianness {
|
||||
type Error = PoseidonSyscallError;
|
||||
|
||||
fn try_from(value: u64) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
x if x == Endianness::BigEndian as u64 => Ok(Endianness::BigEndian),
|
||||
x if x == Endianness::LittleEndian as u64 => Ok(Endianness::LittleEndian),
|
||||
_ => Err(PoseidonSyscallError::InvalidEndianness),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Endianness> for u64 {
|
||||
fn from(value: Endianness) -> Self {
|
||||
match value {
|
||||
Endianness::BigEndian => 0,
|
||||
Endianness::LittleEndian => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Poseidon hash result.
|
||||
#[repr(transparent)]
|
||||
pub struct PoseidonHash(pub [u8; HASH_BYTES]);
|
||||
|
||||
impl PoseidonHash {
|
||||
pub fn new(hash_array: [u8; HASH_BYTES]) -> Self {
|
||||
Self(hash_array)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; HASH_BYTES] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a Poseidon hash for the given data with the given elliptic curve and
|
||||
/// endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use solana_program::poseidon::{hashv, Endianness, Parameters};
|
||||
///
|
||||
/// # fn test() {
|
||||
/// let input1 = [1u8; 32];
|
||||
/// let input2 = [2u8; 32];
|
||||
///
|
||||
/// let hash = hashv(Parameters::Bn254X5, Endianness::BigEndian, &[&input1, &input2]).unwrap();
|
||||
/// assert_eq!(
|
||||
/// hash.to_bytes(),
|
||||
/// [
|
||||
/// 13, 84, 225, 147, 143, 138, 140, 28, 125, 235, 94, 3, 85, 242, 99, 25, 32, 123,
|
||||
/// 132, 254, 156, 162, 206, 27, 38, 231, 53, 200, 41, 130, 25, 144
|
||||
/// ]
|
||||
/// );
|
||||
///
|
||||
/// let hash = hashv(Parameters::Bn254X5, Endianness::LittleEndian, &[&input1, &input2]).unwrap();
|
||||
/// assert_eq!(
|
||||
/// hash.to_bytes(),
|
||||
/// [
|
||||
/// 144, 25, 130, 41, 200, 53, 231, 38, 27, 206, 162, 156, 254, 132, 123, 32, 25, 99,
|
||||
/// 242, 85, 3, 94, 235, 125, 28, 140, 138, 143, 147, 225, 84, 13
|
||||
/// ]
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
#[allow(unused_variables)]
|
||||
pub fn hashv(
|
||||
// This parameter is not used currently, because we support only one curve
|
||||
// (BN254). It should be used in case we add more curves in the future.
|
||||
parameters: Parameters,
|
||||
endianness: Endianness,
|
||||
vals: &[&[u8]],
|
||||
) -> Result<PoseidonHash, PoseidonSyscallError> {
|
||||
// Perform the calculation inline, calling this from within a program is
|
||||
// not supported.
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
{
|
||||
use {
|
||||
ark_bn254::Fr,
|
||||
light_poseidon::{Poseidon, PoseidonBytesHasher, PoseidonError},
|
||||
};
|
||||
|
||||
impl From<PoseidonError> for PoseidonSyscallError {
|
||||
fn from(error: PoseidonError) -> Self {
|
||||
match error {
|
||||
PoseidonError::InvalidNumberOfInputs {
|
||||
inputs: _,
|
||||
max_limit: _,
|
||||
width: _,
|
||||
} => PoseidonSyscallError::InvalidNumberOfInputs,
|
||||
PoseidonError::EmptyInput => PoseidonSyscallError::EmptyInput,
|
||||
PoseidonError::InvalidInputLength {
|
||||
len: _,
|
||||
modulus_bytes_len: _,
|
||||
} => PoseidonSyscallError::InvalidInputLength,
|
||||
PoseidonError::InputLargerThanModulus => {
|
||||
PoseidonSyscallError::InputLargerThanModulus
|
||||
}
|
||||
PoseidonError::VecToArray => PoseidonSyscallError::VecToArray,
|
||||
PoseidonError::U64Tou8 => PoseidonSyscallError::U64Tou8,
|
||||
PoseidonError::InvalidWidthCircom {
|
||||
width: _,
|
||||
max_limit: _,
|
||||
} => PoseidonSyscallError::InvalidWidthCircom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut hasher =
|
||||
Poseidon::<Fr>::new_circom(vals.len()).map_err(PoseidonSyscallError::from)?;
|
||||
let res = match endianness {
|
||||
Endianness::BigEndian => hasher.hash_bytes_be(vals),
|
||||
Endianness::LittleEndian => hasher.hash_bytes_le(vals),
|
||||
}
|
||||
.map_err(PoseidonSyscallError::from)?;
|
||||
|
||||
Ok(PoseidonHash(res))
|
||||
}
|
||||
// Call via a system call to perform the calculation.
|
||||
#[cfg(target_os = "solana")]
|
||||
{
|
||||
let mut hash_result = [0; HASH_BYTES];
|
||||
let result = unsafe {
|
||||
crate::syscalls::sol_poseidon(
|
||||
parameters.into(),
|
||||
endianness.into(),
|
||||
vals as *const _ as *const u8,
|
||||
vals.len() as u64,
|
||||
&mut hash_result as *mut _ as *mut u8,
|
||||
)
|
||||
};
|
||||
|
||||
match result {
|
||||
0 => Ok(PoseidonHash::new(hash_result)),
|
||||
e => Err(PoseidonSyscallError::from(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a Poseidon hash for the given data with the given elliptic curve and
|
||||
/// endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use solana_program::poseidon::{hash, Endianness, Parameters};
|
||||
///
|
||||
/// # fn test() {
|
||||
/// let input = [1u8; 32];
|
||||
///
|
||||
/// let result = hash(Parameters::Bn254X5, Endianness::BigEndian, &input).unwrap();
|
||||
/// assert_eq!(
|
||||
/// result.to_bytes(),
|
||||
/// [
|
||||
/// 5, 191, 172, 229, 129, 238, 97, 119, 204, 25, 198, 197, 99, 99, 166, 136, 130, 241,
|
||||
/// 30, 132, 7, 172, 99, 157, 185, 145, 224, 210, 127, 27, 117, 230
|
||||
/// ],
|
||||
/// );
|
||||
///
|
||||
/// let hash = hash(Parameters::Bn254X5, Endianness::LittleEndian, &input).unwrap();
|
||||
/// assert_eq!(
|
||||
/// hash.to_bytes(),
|
||||
/// [
|
||||
/// 230, 117, 27, 127, 210, 224, 145, 185, 157, 99, 172, 7, 132, 30, 241, 130, 136,
|
||||
/// 166, 99, 99, 197, 198, 25, 204, 119, 97, 238, 129, 229, 172, 191, 5
|
||||
/// ],
|
||||
/// );
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn hash(
|
||||
parameters: Parameters,
|
||||
endianness: Endianness,
|
||||
val: &[u8],
|
||||
) -> Result<PoseidonHash, PoseidonSyscallError> {
|
||||
hashv(parameters, endianness, &[val])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_input_ones_be() {
|
||||
let input = [1u8; 32];
|
||||
|
||||
let hash = hash(Parameters::Bn254X5, Endianness::BigEndian, &input).unwrap();
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
5, 191, 172, 229, 129, 238, 97, 119, 204, 25, 198, 197, 99, 99, 166, 136, 130, 241,
|
||||
30, 132, 7, 172, 99, 157, 185, 145, 224, 210, 127, 27, 117, 230
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_input_ones_le() {
|
||||
let input = [1u8; 32];
|
||||
|
||||
let hash = hash(Parameters::Bn254X5, Endianness::LittleEndian, &input).unwrap();
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
230, 117, 27, 127, 210, 224, 145, 185, 157, 99, 172, 7, 132, 30, 241, 130, 136,
|
||||
166, 99, 99, 197, 198, 25, 204, 119, 97, 238, 129, 229, 172, 191, 5
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_input_ones_twos_be() {
|
||||
let input1 = [1u8; 32];
|
||||
let input2 = [2u8; 32];
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::BigEndian,
|
||||
&[&input1, &input2],
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
13, 84, 225, 147, 143, 138, 140, 28, 125, 235, 94, 3, 85, 242, 99, 25, 32, 123,
|
||||
132, 254, 156, 162, 206, 27, 38, 231, 53, 200, 41, 130, 25, 144
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_input_ones_twos_le() {
|
||||
let input1 = [1u8; 32];
|
||||
let input2 = [2u8; 32];
|
||||
|
||||
let hash = hashv(
|
||||
Parameters::Bn254X5,
|
||||
Endianness::LittleEndian,
|
||||
&[&input1, &input2],
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
hash.to_bytes(),
|
||||
[
|
||||
144, 25, 130, 41, 200, 53, 231, 38, 27, 206, 162, 156, 254, 132, 123, 32, 25, 99,
|
||||
242, 85, 3, 94, 235, 125, 28, 140, 138, 143, 147, 225, 84, 13
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_poseidon_input_one() {
|
||||
let input = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 1,
|
||||
];
|
||||
|
||||
let expected_hashes = [
|
||||
[
|
||||
41, 23, 97, 0, 234, 169, 98, 189, 193, 254, 108, 101, 77, 106, 60, 19, 14, 150,
|
||||
164, 209, 22, 139, 51, 132, 139, 137, 125, 197, 2, 130, 1, 51,
|
||||
],
|
||||
[
|
||||
0, 122, 243, 70, 226, 211, 4, 39, 158, 121, 224, 169, 243, 2, 63, 119, 18, 148,
|
||||
167, 138, 203, 112, 231, 63, 144, 175, 226, 124, 173, 64, 30, 129,
|
||||
],
|
||||
[
|
||||
2, 192, 6, 110, 16, 167, 42, 189, 43, 51, 195, 178, 20, 203, 62, 129, 188, 177,
|
||||
182, 227, 9, 97, 205, 35, 194, 2, 177, 134, 115, 191, 37, 67,
|
||||
],
|
||||
[
|
||||
8, 44, 156, 55, 10, 13, 36, 244, 65, 111, 188, 65, 74, 55, 104, 31, 120, 68, 45,
|
||||
39, 216, 99, 133, 153, 28, 23, 214, 252, 12, 75, 125, 113,
|
||||
],
|
||||
[
|
||||
16, 56, 150, 5, 174, 104, 141, 79, 20, 219, 133, 49, 34, 196, 125, 102, 168, 3,
|
||||
199, 43, 65, 88, 156, 177, 191, 134, 135, 65, 178, 6, 185, 187,
|
||||
],
|
||||
[
|
||||
42, 115, 246, 121, 50, 140, 62, 171, 114, 74, 163, 229, 189, 191, 80, 179, 144, 53,
|
||||
215, 114, 159, 19, 91, 151, 9, 137, 15, 133, 197, 220, 94, 118,
|
||||
],
|
||||
[
|
||||
34, 118, 49, 10, 167, 243, 52, 58, 40, 66, 20, 19, 157, 157, 169, 89, 190, 42, 49,
|
||||
178, 199, 8, 165, 248, 25, 84, 178, 101, 229, 58, 48, 184,
|
||||
],
|
||||
[
|
||||
23, 126, 20, 83, 196, 70, 225, 176, 125, 43, 66, 51, 66, 81, 71, 9, 92, 79, 202,
|
||||
187, 35, 61, 35, 11, 109, 70, 162, 20, 217, 91, 40, 132,
|
||||
],
|
||||
[
|
||||
14, 143, 238, 47, 228, 157, 163, 15, 222, 235, 72, 196, 46, 187, 68, 204, 110, 231,
|
||||
5, 95, 97, 251, 202, 94, 49, 59, 138, 95, 202, 131, 76, 71,
|
||||
],
|
||||
[
|
||||
46, 196, 198, 94, 99, 120, 171, 140, 115, 48, 133, 79, 74, 112, 119, 193, 255, 146,
|
||||
96, 228, 72, 133, 196, 184, 29, 209, 49, 173, 58, 134, 205, 150,
|
||||
],
|
||||
[
|
||||
0, 113, 61, 65, 236, 166, 53, 241, 23, 212, 236, 188, 235, 95, 58, 102, 220, 65,
|
||||
66, 235, 112, 181, 103, 101, 188, 53, 143, 27, 236, 64, 187, 155,
|
||||
],
|
||||
[
|
||||
20, 57, 11, 224, 186, 239, 36, 155, 212, 124, 101, 221, 172, 101, 194, 229, 46,
|
||||
133, 19, 192, 129, 193, 205, 114, 201, 128, 6, 9, 142, 154, 143, 190,
|
||||
],
|
||||
];
|
||||
|
||||
for (i, expected_hash) in expected_hashes.iter().enumerate() {
|
||||
let inputs = vec![&input; i + 1]
|
||||
.into_iter()
|
||||
.map(|arr| &arr[..])
|
||||
.collect::<Vec<_>>();
|
||||
let hash = hashv(Parameters::Bn254X5, Endianness::BigEndian, &inputs).unwrap();
|
||||
assert_eq!(hash.to_bytes(), *expected_hash);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ define_syscall!(fn sol_curve_pairing_map(curve_id: u64, point: *const u8, result
|
|||
define_syscall!(fn sol_alt_bn128_group_op(group_op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
|
||||
define_syscall!(fn sol_big_mod_exp(params: *const u8, result: *mut u8) -> u64);
|
||||
define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64);
|
||||
define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
|
||||
|
||||
#[cfg(target_feature = "static-syscalls")]
|
||||
pub const fn sys_hash(name: &str) -> usize {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana poseidon system call
|
||||
**/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a Poseidon hash result
|
||||
*/
|
||||
#define POSEIDON_RESULT_LENGTH 32
|
||||
|
||||
/**
|
||||
* Configuration using the Barreto–Naehrig curve with an embedding degree of
|
||||
* 12, defined over a 254-bit prime field.
|
||||
*
|
||||
* Configuration Details:
|
||||
* - S-Box: x^5
|
||||
* - Width: 2 <= t <= 13
|
||||
* - Inputs: 1 <= n <= 12
|
||||
* - Full rounds: 8
|
||||
* - Partial rounds: Depending on width: [56, 57, 56, 60, 60, 63, 64, 63,
|
||||
* 60, 66, 60, 65]
|
||||
*/
|
||||
#define POSEIDON_PARAMETERS_BN254_X5 0
|
||||
|
||||
/**
|
||||
* Big-endian inputs and output
|
||||
*/
|
||||
#define POSEIDON_ENDIANNESS_BIG_ENDIAN 0
|
||||
|
||||
/**
|
||||
* Little-endian inputs and output
|
||||
*/
|
||||
#define POSEIDON_ENDIANNESS_LITTLE_ENDIAN 1
|
||||
|
||||
/**
|
||||
* Poseidon
|
||||
*
|
||||
* @param parameters Configuration parameters for the hash function
|
||||
* @param endianness Endianness of inputs and result
|
||||
* @param bytes Array of byte arrays
|
||||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
@SYSCALL uint64_t sol_poseidon(
|
||||
const uint64_t parameters,
|
||||
const uint64_t endianness,
|
||||
const SolBytes *bytes,
|
||||
const uint64_t bytes_len,
|
||||
uint8_t *result
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana poseidon system call
|
||||
**/
|
||||
|
||||
#include <sol/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Length of a Poseidon hash result
|
||||
*/
|
||||
#define POSEIDON_RESULT_LENGTH 32
|
||||
|
||||
/**
|
||||
* Configuration using the Barreto–Naehrig curve with an embedding degree of
|
||||
* 12, defined over a 254-bit prime field.
|
||||
*
|
||||
* Configuration Details:
|
||||
* - S-Box: x^5
|
||||
* - Width: 2 <= t <= 13
|
||||
* - Inputs: 1 <= n <= 12
|
||||
* - Full rounds: 8
|
||||
* - Partial rounds: Depending on width: [56, 57, 56, 60, 60, 63, 64, 63,
|
||||
* 60, 66, 60, 65]
|
||||
*/
|
||||
#define POSEIDON_PARAMETERS_BN254_X5 0
|
||||
|
||||
/**
|
||||
* Big-endian inputs and output
|
||||
*/
|
||||
#define POSEIDON_ENDIANNESS_BIG_ENDIAN 0
|
||||
|
||||
/**
|
||||
* Little-endian inputs and output
|
||||
*/
|
||||
#define POSEIDON_ENDIANNESS_LITTLE_ENDIAN 1
|
||||
|
||||
/**
|
||||
* Poseidon
|
||||
*
|
||||
* @param parameters Configuration parameters for the hash function
|
||||
* @param endianness Endianness of inputs and result
|
||||
* @param bytes Array of byte arrays
|
||||
* @param bytes_len Number of byte arrays
|
||||
* @param result 32 byte array to hold the result
|
||||
*/
|
||||
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/sbf/c/inc/sol/inc/poseidon.inc AND RUN `cargo run --bin gen-headers` */
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_poseidon(
|
||||
const uint64_t parameters,
|
||||
const uint64_t endianness,
|
||||
const SolBytes *bytes,
|
||||
const uint64_t bytes_len,
|
||||
uint8_t *result
|
||||
);
|
||||
#else
|
||||
typedef uint64_t(*sol_poseidon_pointer_type)(
|
||||
const uint64_t parameters,
|
||||
const uint64_t endianness,
|
||||
const SolBytes *bytes,
|
||||
const uint64_t bytes_len,
|
||||
uint8_t *result
|
||||
);
|
||||
static uint64_t sol_poseidon(
|
||||
const uint64_t parameters arg1,
|
||||
const uint64_t endianness arg2,
|
||||
const SolBytes *bytes arg3,
|
||||
const uint64_t bytes_len arg4,
|
||||
uint8_t *result
|
||||
arg5) {
|
||||
sol_poseidon_pointer_type sol_poseidon_pointer = (sol_poseidon_pointer_type) 3298065441;
|
||||
return sol_poseidon_pointer(arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -691,6 +691,10 @@ pub mod revise_turbine_epoch_stakes {
|
|||
solana_sdk::declare_id!("BTWmtJC8U5ZLMbBUUA1k6As62sYjPEjAiNAT55xYGdJU");
|
||||
}
|
||||
|
||||
pub mod enable_poseidon_syscall {
|
||||
solana_sdk::declare_id!("Pos1111111111111111111111111111111111111111");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -856,6 +860,7 @@ lazy_static! {
|
|||
(last_restart_slot_sysvar::id(), "enable new sysvar last_restart_slot"),
|
||||
(reduce_stake_warmup_cooldown::id(), "reduce stake warmup cooldown from 25% to 9%"),
|
||||
(revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"),
|
||||
(enable_poseidon_syscall::id(), "Enable Poseidon syscall"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
|
|
@ -49,10 +49,11 @@ pub use solana_program::{
|
|||
declare_sysvar_id, decode_error, ed25519_program, epoch_rewards, epoch_schedule,
|
||||
fee_calculator, impl_sysvar_get, incinerator, instruction, keccak, lamports,
|
||||
loader_instruction, loader_upgradeable_instruction, loader_v4, loader_v4_instruction, message,
|
||||
msg, native_token, nonce, program, program_error, program_memory, program_option, program_pack,
|
||||
rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint, serialize_utils,
|
||||
short_vec, slot_hashes, slot_history, stable_layout, stake, stake_history, syscalls,
|
||||
system_instruction, system_program, sysvar, unchecked_div_by_const, vote, wasm_bindgen,
|
||||
msg, native_token, nonce, poseidon, program, program_error, program_memory, program_option,
|
||||
program_pack, rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint,
|
||||
serialize_utils, short_vec, slot_hashes, slot_history, stable_layout, stake, stake_history,
|
||||
syscalls, system_instruction, system_program, sysvar, unchecked_div_by_const, vote,
|
||||
wasm_bindgen,
|
||||
};
|
||||
|
||||
pub mod account;
|
||||
|
|
Loading…
Reference in New Issue