Big integer modular exponentiation (EIP-198) (#28503)
* big_mod_exp impl * fix programs/sbf/Cargo.lock * ComputeBudget impl * update compute_budget * compute_budget update * fix build * fix tests * fix cargo clippy * fix clippy * fix bpf_loader dependency sorting * fix sorting * fix merge from master * fix cargo fmt * fix C-tests * fix cargo fmt * comments apply * fix programs/sbf/Cargo.lock * update compude_budget cost * remove whitespaces * fix cargo fmt Co-authored-by: sinev-valentine <sinev-valentine@yandex.ru>
This commit is contained in:
parent
9a5aca36e6
commit
5f7fea100a
|
@ -5986,6 +5986,7 @@ dependencies = [
|
|||
"libsecp256k1",
|
||||
"log",
|
||||
"memoffset",
|
||||
"num-bigint 0.4.3",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot 0.12.1",
|
||||
|
|
|
@ -107,6 +107,8 @@ pub struct ComputeBudget {
|
|||
/// + alt_bn128_pairing_one_pair_cost_other * (num_elems - 1)
|
||||
pub alt_bn128_pairing_one_pair_cost_first: u64,
|
||||
pub alt_bn128_pairing_one_pair_cost_other: u64,
|
||||
/// Big integer modular exponentiation cost
|
||||
pub big_modular_exponentiation_cost: u64,
|
||||
}
|
||||
|
||||
impl Default for ComputeBudget {
|
||||
|
@ -154,6 +156,7 @@ impl ComputeBudget {
|
|||
alt_bn128_multiplication_cost: 3_840,
|
||||
alt_bn128_pairing_one_pair_cost_first: 36_364,
|
||||
alt_bn128_pairing_one_pair_cost_other: 12_121,
|
||||
big_modular_exponentiation_cost: 33,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,14 @@ use {
|
|||
ALT_BN128_ADDITION_OUTPUT_LEN, ALT_BN128_MULTIPLICATION_OUTPUT_LEN,
|
||||
ALT_BN128_PAIRING_ELEMENT_LEN, ALT_BN128_PAIRING_OUTPUT_LEN,
|
||||
},
|
||||
big_mod_exp::{big_mod_exp, BigModExpParams},
|
||||
blake3, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
|
||||
entrypoint::{BPF_ALIGN_OF_U128, MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||
feature_set::FeatureSet,
|
||||
feature_set::{
|
||||
self, blake3_syscall_enabled, check_syscall_outputs_do_not_overlap,
|
||||
curve25519_syscall_enabled, disable_cpi_setting_executable_and_rent_epoch,
|
||||
disable_fees_sysvar, enable_alt_bn128_syscall,
|
||||
disable_fees_sysvar, enable_alt_bn128_syscall, enable_big_mod_exp_syscall,
|
||||
enable_early_verification_of_account_modifications,
|
||||
error_on_syscall_bpf_function_hash_collisions, libsecp256k1_0_5_upgrade_enabled,
|
||||
limit_secp256k1_recovery_id, reject_callx_r10,
|
||||
|
@ -186,6 +187,7 @@ pub fn create_loader<'a>(
|
|||
};
|
||||
|
||||
let enable_alt_bn128_syscall = feature_set.is_active(&enable_alt_bn128_syscall::id());
|
||||
let enable_big_mod_exp_syscall = feature_set.is_active(&enable_big_mod_exp_syscall::id());
|
||||
let blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
|
||||
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_syscall_enabled::id());
|
||||
let disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id());
|
||||
|
@ -306,6 +308,14 @@ pub fn create_loader<'a>(
|
|||
"sol_alt_bn128_group_op",
|
||||
SyscallAltBn128::call,
|
||||
)?;
|
||||
|
||||
// Big_mod_exp
|
||||
register_feature_gated_function!(
|
||||
result,
|
||||
enable_big_mod_exp_syscall,
|
||||
"sol_big_mod_exp",
|
||||
SyscallBigModExp::call,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Log data
|
||||
|
@ -1718,6 +1728,80 @@ declare_syscall!(
|
|||
}
|
||||
);
|
||||
|
||||
declare_syscall!(
|
||||
/// Big integer modular exponentiation
|
||||
SyscallBigModExp,
|
||||
fn inner_call(
|
||||
invoke_context: &mut InvokeContext,
|
||||
params: u64,
|
||||
return_value: u64,
|
||||
_arg3: u64,
|
||||
_arg4: u64,
|
||||
_arg5: u64,
|
||||
memory_mapping: &mut MemoryMapping,
|
||||
) -> Result<u64, EbpfError> {
|
||||
let params = &translate_slice::<BigModExpParams>(
|
||||
memory_mapping,
|
||||
params,
|
||||
1,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?
|
||||
.get(0)
|
||||
.ok_or(SyscallError::InvalidLength)?;
|
||||
|
||||
let input_len: u64 = std::cmp::max(params.base_len, params.exponent_len);
|
||||
let input_len: u64 = std::cmp::max(input_len, params.modulus_len);
|
||||
|
||||
let budget = invoke_context.get_compute_budget();
|
||||
consume_compute_meter(
|
||||
invoke_context,
|
||||
budget.syscall_base_cost.saturating_add(
|
||||
input_len
|
||||
.saturating_mul(input_len)
|
||||
.saturating_div(budget.big_modular_exponentiation_cost),
|
||||
),
|
||||
)?;
|
||||
|
||||
let base = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
params.base as *const _ as *const u8 as u64,
|
||||
params.base_len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
|
||||
let exponent = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
params.exponent as *const _ as *const u8 as u64,
|
||||
params.exponent_len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
|
||||
let modulus = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
params.modulus as *const _ as *const u8 as u64,
|
||||
params.modulus_len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
|
||||
let value = big_mod_exp(base, exponent, modulus);
|
||||
|
||||
let return_value = translate_slice_mut::<u8>(
|
||||
memory_mapping,
|
||||
return_value,
|
||||
params.modulus_len,
|
||||
invoke_context.get_check_aligned(),
|
||||
invoke_context.get_check_size(),
|
||||
)?;
|
||||
return_value.copy_from_slice(value.as_slice());
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[allow(deprecated)]
|
||||
|
|
|
@ -4319,6 +4319,16 @@ dependencies = [
|
|||
"solana-program 1.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-bpf-rust-big-mod-exp"
|
||||
version = "1.15.0"
|
||||
dependencies = [
|
||||
"array-bytes",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"solana-program 1.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-bucket-map"
|
||||
version = "1.15.0"
|
||||
|
@ -4974,6 +4984,7 @@ dependencies = [
|
|||
"libsecp256k1 0.6.0",
|
||||
"log",
|
||||
"memoffset",
|
||||
"num-bigint 0.4.3",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot 0.12.1",
|
||||
|
|
|
@ -52,6 +52,7 @@ members = [
|
|||
"rust/128bit_dep",
|
||||
"rust/alloc",
|
||||
"rust/alt_bn128",
|
||||
"rust/big_mod_exp",
|
||||
"rust/call_depth",
|
||||
"rust/caller_access",
|
||||
"rust/curve25519",
|
||||
|
|
|
@ -61,6 +61,7 @@ fn main() {
|
|||
"128bit",
|
||||
"alloc",
|
||||
"alt_bn128",
|
||||
"big_mod_exp",
|
||||
"call_depth",
|
||||
"caller_access",
|
||||
"curve25519",
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @brief Big integer modular exponentiation Syscall test
|
||||
*/
|
||||
|
||||
#include <solana_sdk.h>
|
||||
|
||||
extern uint64_t entrypoint(const uint8_t *input) {
|
||||
|
||||
struct BigModExpParam{
|
||||
char* base;
|
||||
size_t base_len;
|
||||
char* exponent;
|
||||
size_t exponent_len;
|
||||
char* modulus;
|
||||
size_t modulus_len;
|
||||
} params;
|
||||
|
||||
uint8_t base[32] = {
|
||||
0x98, 0x74, 0x23, 0x14, 0x72, 0x31, 0x74, 0x32, 0x84, 0x79, 0x23, 0x17, 0x43, 0x92, 0x87, 0x49,
|
||||
0x18, 0x23, 0x74, 0x39, 0x28, 0x74, 0x92, 0x37, 0x49, 0x32, 0x87, 0x19, 0x37, 0x28, 0x97, 0x19
|
||||
};
|
||||
uint8_t exponent[32] = {
|
||||
0x09, 0x48, 0x40, 0x39, 0x85, 0x40, 0x12, 0x32, 0x88, 0x94, 0x38, 0x57, 0x94, 0x75, 0x81, 0x23,
|
||||
0x47, 0x23, 0x20, 0x99, 0x08, 0x00, 0x51, 0x35, 0x61, 0x65, 0x12, 0x61, 0x66, 0x26, 0x62, 0x22
|
||||
};
|
||||
uint8_t modulus[32] = {
|
||||
0x25, 0x53, 0x23, 0x21, 0xa2, 0x14, 0x32, 0x14, 0x23, 0x12, 0x42, 0x12, 0x22, 0x22, 0x24, 0x22,
|
||||
0x2b, 0x24, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x24, 0x44
|
||||
};
|
||||
uint8_t expected[32] = {
|
||||
0x22, 0x0e, 0xce, 0x1c, 0x42, 0x62, 0x4e, 0x98, 0xae, 0xe7, 0xeb, 0x86, 0x57, 0x8b, 0x2f, 0xe5,
|
||||
0xc4, 0x85, 0x5d, 0xff, 0xac, 0xcb, 0x43, 0xcc, 0xbb, 0x70, 0x8a, 0x3a, 0xb3, 0x7f, 0x18, 0x4d
|
||||
};
|
||||
uint8_t result[32];
|
||||
|
||||
params.base = (char*) base;
|
||||
params.base_len = sizeof(base);
|
||||
params.exponent = (char*) exponent;
|
||||
params.exponent_len = sizeof(exponent);
|
||||
params.modulus = (char*) modulus;
|
||||
params.modulus_len = sizeof(modulus);
|
||||
|
||||
uint64_t result_code = sol_big_mod_exp((uint8_t *) ¶ms, result);
|
||||
|
||||
sol_assert(0 == result_code);
|
||||
sol_assert(0 == sol_memcmp(result, expected, 32));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "solana-bpf-rust-big-mod-exp"
|
||||
version = "1.15.0"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
documentation = "https://docs.rs/solana-bpf-rust-big-mod-exp"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
array-bytes = "=1.4.1"
|
||||
serde = { version = "1.0.112", features = ["derive"] }
|
||||
serde_json = "1.0.56"
|
||||
solana-program = { path = "../../../../sdk/program", version = "=1.15.0" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -0,0 +1,93 @@
|
|||
//! Big_mod_exp Syscall tests
|
||||
|
||||
extern crate solana_program;
|
||||
use solana_program::{big_mod_exp::big_mod_exp, custom_panic_default, msg};
|
||||
|
||||
fn big_mod_exp_test() {
|
||||
#[derive(serde::Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct TestCase {
|
||||
base: String,
|
||||
exponent: String,
|
||||
modulus: String,
|
||||
expected: String,
|
||||
}
|
||||
|
||||
let test_data = r#"[
|
||||
{
|
||||
"Base": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Exponent": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Modulus": "111111111111111111111111111111111111111111111111111111111111110A",
|
||||
"Expected": "0A7074864588D6847F33A168209E516F60005A0CEC3F33AAF70E8002FE964BCD"
|
||||
},
|
||||
{
|
||||
"Base": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Exponent": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Modulus": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"Base": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"Exponent": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"Modulus": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Expected": "1111111111111111111111111111111111111111111111111111111111111111"
|
||||
},
|
||||
{
|
||||
"Base": "9874231472317432847923174392874918237439287492374932871937289719",
|
||||
"Exponent": "0948403985401232889438579475812347232099080051356165126166266222",
|
||||
"Modulus": "25532321a214321423124212222224222b242222222222222222222222222444",
|
||||
"Expected": "220ECE1C42624E98AEE7EB86578B2FE5C4855DFFACCB43CCBB708A3AB37F184D"
|
||||
},
|
||||
{
|
||||
"Base": "3494396663463663636363662632666565656456646566786786676786768766",
|
||||
"Exponent": "2324324333246536456354655645656616169896565698987033121934984955",
|
||||
"Modulus": "0218305479243590485092843590249879879842313131156656565565656566",
|
||||
"Expected": "012F2865E8B9E79B645FCE3A9E04156483AE1F9833F6BFCF86FCA38FC2D5BEF0"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000005",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000004"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000064",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000019"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
]"#;
|
||||
|
||||
let test_cases: Vec<TestCase> = serde_json::from_str(test_data).unwrap();
|
||||
test_cases.iter().for_each(|test| {
|
||||
let base = array_bytes::hex2bytes_unchecked(&test.base);
|
||||
let exponent = array_bytes::hex2bytes_unchecked(&test.exponent);
|
||||
let modulus = array_bytes::hex2bytes_unchecked(&test.modulus);
|
||||
let expected = array_bytes::hex2bytes_unchecked(&test.expected);
|
||||
let result = big_mod_exp(base.as_slice(), exponent.as_slice(), modulus.as_slice());
|
||||
assert_eq!(result, expected);
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn entrypoint(_input: *mut u8) -> u64 {
|
||||
msg!("big_mod_exp");
|
||||
|
||||
big_mod_exp_test();
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
custom_panic_default!();
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana big_mod_exp system call
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Big integer modular exponentiation
|
||||
*
|
||||
* @param bytes Pointer to BigModExpParam struct
|
||||
* @param result 32 byte array to hold the result
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/bpf/c/inc/sol/inc/big_mod_exp.inc AND RUN `cargo run --bin gen-headers` */
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_big_mod_exp(const uint8_t *, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_big_mod_exp_pointer_type)(const uint8_t *, uint8_t *);
|
||||
static uint64_t sol_big_mod_exp(const uint8_t * arg1, uint8_t * arg2) {
|
||||
sol_big_mod_exp_pointer_type sol_big_mod_exp_pointer = (sol_big_mod_exp_pointer_type) 2014202901;
|
||||
return sol_big_mod_exp_pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana big_mod_exp system call
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Big integer modular exponentiation
|
||||
*
|
||||
* @param bytes Pointer to BigModExpParam struct
|
||||
* @param result 32 byte array to hold the result
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
@SYSCALL uint64_t sol_big_mod_exp(const uint8_t *, uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <sol/alt_bn128.h>
|
||||
#include <sol/assert.h>
|
||||
#include <sol/big_mod_exp.h>
|
||||
#include <sol/blake3.h>
|
||||
#include <sol/cpi.h>
|
||||
#include <sol/deserialize.h>
|
||||
|
|
|
@ -47,6 +47,7 @@ curve25519-dalek = { version = "3.2.1", features = ["serde"] }
|
|||
itertools = "0.10.5"
|
||||
libc = { version = "0.2.126", features = ["extra_traits"] }
|
||||
libsecp256k1 = "0.6.0"
|
||||
num-bigint = "0.4.3"
|
||||
rand = "0.7"
|
||||
rand_chacha = { version = "0.2.2", default-features = true, features = ["simd", "std"] }
|
||||
tiny-bip39 = "0.8.2"
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
#[repr(C)]
|
||||
pub struct BigModExpParams {
|
||||
pub base: *const u8,
|
||||
pub base_len: u64,
|
||||
pub exponent: *const u8,
|
||||
pub exponent_len: u64,
|
||||
pub modulus: *const u8,
|
||||
pub modulus_len: u64,
|
||||
}
|
||||
|
||||
/// Big integer modular exponentiation
|
||||
pub fn big_mod_exp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec<u8> {
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
{
|
||||
use {
|
||||
num_bigint::BigUint,
|
||||
num_traits::{One, Zero},
|
||||
};
|
||||
|
||||
let modulus_len = modulus.len();
|
||||
let base = BigUint::from_bytes_be(base);
|
||||
let exponent = BigUint::from_bytes_be(exponent);
|
||||
let modulus = BigUint::from_bytes_be(modulus);
|
||||
|
||||
if modulus.is_zero() || modulus.is_one() {
|
||||
return vec![0_u8; modulus_len];
|
||||
}
|
||||
|
||||
let ret_int = base.modpow(&exponent, &modulus);
|
||||
let ret_int = ret_int.to_bytes_be();
|
||||
let mut return_value = vec![0_u8; modulus_len.saturating_sub(ret_int.len())];
|
||||
return_value.extend(ret_int);
|
||||
return_value
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solana")]
|
||||
{
|
||||
let mut return_value = vec![0_u8; modulus.len()];
|
||||
|
||||
let param = BigModExpParams {
|
||||
base: base as *const _ as *const u8,
|
||||
base_len: base.len() as u64,
|
||||
exponent: exponent as *const _ as *const u8,
|
||||
exponent_len: exponent.len() as u64,
|
||||
modulus: modulus as *const _ as *const u8,
|
||||
modulus_len: modulus.len() as u64,
|
||||
};
|
||||
unsafe {
|
||||
crate::syscalls::sol_big_mod_exp(
|
||||
¶m as *const _ as *const u8,
|
||||
return_value.as_mut_slice() as *mut _ as *mut u8,
|
||||
)
|
||||
};
|
||||
|
||||
return_value
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn big_mod_exp_test() {
|
||||
#[derive(serde::Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct TestCase {
|
||||
base: String,
|
||||
exponent: String,
|
||||
modulus: String,
|
||||
expected: String,
|
||||
}
|
||||
|
||||
let test_data = r#"[
|
||||
{
|
||||
"Base": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Exponent": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Modulus": "111111111111111111111111111111111111111111111111111111111111110A",
|
||||
"Expected": "0A7074864588D6847F33A168209E516F60005A0CEC3F33AAF70E8002FE964BCD"
|
||||
},
|
||||
{
|
||||
"Base": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Exponent": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Modulus": "1111111111111111111111111111111111111111111111111111111111111111",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"Base": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"Exponent": "3333333333333333333333333333333333333333333333333333333333333333",
|
||||
"Modulus": "2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"Expected": "1111111111111111111111111111111111111111111111111111111111111111"
|
||||
},
|
||||
{
|
||||
"Base": "9874231472317432847923174392874918237439287492374932871937289719",
|
||||
"Exponent": "0948403985401232889438579475812347232099080051356165126166266222",
|
||||
"Modulus": "25532321a214321423124212222224222b242222222222222222222222222444",
|
||||
"Expected": "220ECE1C42624E98AEE7EB86578B2FE5C4855DFFACCB43CCBB708A3AB37F184D"
|
||||
},
|
||||
{
|
||||
"Base": "3494396663463663636363662632666565656456646566786786676786768766",
|
||||
"Exponent": "2324324333246536456354655645656616169896565698987033121934984955",
|
||||
"Modulus": "0218305479243590485092843590249879879842313131156656565565656566",
|
||||
"Expected": "012F2865E8B9E79B645FCE3A9E04156483AE1F9833F6BFCF86FCA38FC2D5BEF0"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000005",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000004"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000064",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000019"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"Base": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Exponent": "0000000000000000000000000000000000000000000000000000000000000019",
|
||||
"Modulus": "0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"Expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
]"#;
|
||||
|
||||
let test_cases: Vec<TestCase> = serde_json::from_str(test_data).unwrap();
|
||||
test_cases.iter().for_each(|test| {
|
||||
let base = array_bytes::hex2bytes_unchecked(&test.base);
|
||||
let exponent = array_bytes::hex2bytes_unchecked(&test.exponent);
|
||||
let modulus = array_bytes::hex2bytes_unchecked(&test.modulus);
|
||||
let expected = array_bytes::hex2bytes_unchecked(&test.expected);
|
||||
let result = big_mod_exp(base.as_slice(), exponent.as_slice(), modulus.as_slice());
|
||||
assert_eq!(result, expected);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -478,6 +478,7 @@ pub mod account_info;
|
|||
pub mod address_lookup_table_account;
|
||||
pub mod alt_bn128;
|
||||
pub(crate) mod atomic_u64;
|
||||
pub mod big_mod_exp;
|
||||
pub mod blake3;
|
||||
pub mod borsh;
|
||||
pub mod bpf_loader;
|
||||
|
|
|
@ -66,6 +66,7 @@ define_syscall!(fn sol_curve_group_op(curve_id: u64, group_op: u64, left_input_a
|
|||
define_syscall!(fn sol_curve_multiscalar_mul(curve_id: u64, scalars_addr: *const u8, points_addr: *const u8, points_len: u64, result_point_addr: *mut u8) -> u64);
|
||||
define_syscall!(fn sol_curve_pairing_map(curve_id: u64, point: *const u8, result: *mut u8) -> u64);
|
||||
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);
|
||||
|
||||
#[cfg(target_feature = "static-syscalls")]
|
||||
pub const fn sys_hash(name: &str) -> usize {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana big_mod_exp system call
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Big integer modular exponentiation
|
||||
*
|
||||
* @param bytes Pointer to BigModExpParam struct
|
||||
* @param result 32 byte array to hold the result
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/sbf/c/inc/sol/inc/big_mod_exp.inc AND RUN `cargo run --bin gen-headers` */
|
||||
#ifndef SOL_SBFV2
|
||||
uint64_t sol_big_mod_exp(const uint8_t *, uint8_t *);
|
||||
#else
|
||||
typedef uint64_t(*sol_big_mod_exp_pointer_type)(const uint8_t *, uint8_t *);
|
||||
static uint64_t sol_big_mod_exp(const uint8_t * arg1, uint8_t * arg2) {
|
||||
sol_big_mod_exp_pointer_type sol_big_mod_exp_pointer = (sol_big_mod_exp_pointer_type) 2014202901;
|
||||
return sol_big_mod_exp_pointer(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
/**
|
||||
* @brief Solana big_mod_exp system call
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Big integer modular exponentiation
|
||||
*
|
||||
* @param bytes Pointer to BigModExpParam struct
|
||||
* @param result 32 byte array to hold the result
|
||||
* @return 0 if executed successfully
|
||||
*/
|
||||
@SYSCALL uint64_t sol_big_mod_exp(const uint8_t *, uint8_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include <sol/assert.h>
|
||||
#include <sol/big_mod_exp.h>
|
||||
#include <sol/blake3.h>
|
||||
#include <sol/cpi.h>
|
||||
#include <sol/deserialize.h>
|
||||
|
|
|
@ -586,6 +586,10 @@ pub mod update_hashes_per_tick {
|
|||
solana_sdk::declare_id!("3uFHb9oKdGfgZGJK9EHaAXN4USvnQtAFC13Fh5gGFS5B");
|
||||
}
|
||||
|
||||
pub mod enable_big_mod_exp_syscall {
|
||||
solana_sdk::declare_id!("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXBGMDEXP");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
|
@ -727,6 +731,7 @@ lazy_static! {
|
|||
(keep_merkle_shreds::id(), "keep merkle shreds #29711"),
|
||||
(move_serialized_len_ptr_in_cpi::id(), "cpi ignore serialized_len_ptr #29592"),
|
||||
(update_hashes_per_tick::id(), "Update desired hashes per tick on epoch boundary"),
|
||||
(enable_big_mod_exp_syscall::id(), "add big_mod_exp syscall #28503"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
|
|
@ -43,7 +43,7 @@ pub use signer::signers;
|
|||
#[cfg(not(target_os = "solana"))]
|
||||
pub use solana_program::program_stubs;
|
||||
pub use solana_program::{
|
||||
account_info, address_lookup_table_account, alt_bn128, blake3, borsh, bpf_loader,
|
||||
account_info, address_lookup_table_account, alt_bn128, big_mod_exp, blake3, borsh, bpf_loader,
|
||||
bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
|
||||
custom_panic_default, debug_account_data, declare_deprecated_sysvar_id, declare_sysvar_id,
|
||||
decode_error, ed25519_program, epoch_schedule, fee_calculator, impl_sysvar_get, incinerator,
|
||||
|
|
Loading…
Reference in New Issue