Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug: When using dynamic linking, auth will be loaded repeatedly. #27

Merged
merged 27 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d6656ec
Fix bug: When using dynamic linking, auth will be loaded repeatedly.
joii2020 Dec 8, 2023
8f5ee08
Update Readme
joii2020 Dec 7, 2023
2c63cf0
test support auth-rust-lock
joii2020 Dec 12, 2023
c571024
ckb-auth-rs dl context in static memory
joii2020 Dec 12, 2023
b5083c6
Fix bug in auht-rust-lock
joii2020 Dec 12, 2023
d2b6b19
Add Cargo.lock
joii2020 Dec 12, 2023
e4204ea
Support feature enable-dynamic-library
joii2020 Dec 13, 2023
298815c
Add testcase about ckb-auth-rs features
joii2020 Dec 13, 2023
8f65686
Execute ckb-auth twice consecutively in auth-rust-lock
joii2020 Dec 13, 2023
a826903
Fix CI: rust-demo-tests build before testing
joii2020 Dec 13, 2023
f7391c1
ckb-auth-rs: Defaule enable dynamic-library
joii2020 Dec 13, 2023
d5aa298
Replace DynamicLinking to DynamicLibrary in ckb-auth-rs
joii2020 Dec 13, 2023
8b69cc2
Fix CI: aut-rust-demo add no default features
joii2020 Dec 13, 2023
0cfc9c4
Add more comments
XuJiandong Dec 13, 2023
8d5bc21
Merge pull request #3 from XuJiandong/add-comments
joii2020 Dec 13, 2023
bd31ce4
C ckb_auht.h support multi dynamic lib
joii2020 Dec 13, 2023
2d0847f
Some numbers are replaced with macros
joii2020 Dec 13, 2023
bc07adb
ckb_auth.h: EntryCategoryDynamicLinking replace to EntryCategoryDynam…
joii2020 Dec 13, 2023
71ea418
Init dynamic library global cache to zero
joii2020 Dec 13, 2023
8ec271c
Add comment
joii2020 Dec 13, 2023
14531e0
Fix CI: warning with docker
joii2020 Dec 13, 2023
bfc2db8
Update Cargo.lock
joii2020 Dec 13, 2023
e9b77fd
Add macro CKB_AUTH_DISABLE_DYNAMIC_LIB.
joii2020 Dec 13, 2023
d493e86
Add testcase: When disable dynamic lib
joii2020 Dec 13, 2023
9a2f645
Update auth.md, about dynamic library
joii2020 Dec 13, 2023
451d581
Fix CI: auth-c-lock add auth_c_lock_disable_dl
joii2020 Dec 13, 2023
04a659e
rust dynamic lib cache remains aligned
joii2020 Dec 18, 2023
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
15 changes: 10 additions & 5 deletions c/ckb_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,19 +120,24 @@ typedef int (*ckb_auth_validate_t)(uint8_t auth_algorithm_id,
uint32_t pubkey_hash_size);

static uint8_t g_code_buff[300 * 1024] __attribute__((aligned(RISCV_PGSIZE)));
static void* g_code_handle;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

init it to zero.


int ckb_auth(CkbEntryType *entry, CkbAuthType *id, const uint8_t *signature,
uint32_t signature_size, const uint8_t *message32) {
int err = 0;
if (entry->entry_category == EntryCategoryDynamicLinking) {
void *handle = NULL;
size_t consumed_size = 0;
err = ckb_dlopen2(entry->code_hash, entry->hash_type, g_code_buff,
sizeof(g_code_buff), &handle, &consumed_size);
if (err != 0) return err;

if (!g_code_handle) {
err = ckb_dlopen2(entry->code_hash, entry->hash_type, g_code_buff,
sizeof(g_code_buff), &g_code_handle, &consumed_size);
if (err != 0) {
return err;
}
}

ckb_auth_validate_t func =
(ckb_auth_validate_t)ckb_dlsym(handle, "ckb_auth_validate");
(ckb_auth_validate_t)ckb_dlsym(g_code_handle, "ckb_auth_validate");
if (func == 0) {
return CKB_INVALID_DATA;
}
Expand Down
6 changes: 6 additions & 0 deletions ckb-auth-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ edition = "2021"
default = []
ckb2023 = ["ckb-std/ckb2023"]

enable-dynamic-library = ["lazy_static"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use this feature as default

dynamic-library-memory-200 = ["enable-dynamic-library"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use this feature as default.

dynamic-library-memory-400 = ["enable-dynamic-library"]
dynamic-library-memory-600 = ["enable-dynamic-library"]

[dependencies]
ckb-std = "0.14.3"
lazy_static = { version = "1.4.0", optional = true, features = ["spin_no_std"] }

[target.'cfg(target_arch = "riscv64")'.dependencies]
hex = { version = "0.4.3", default-features = false, features = ["alloc"]}
Expand Down
130 changes: 8 additions & 122 deletions ckb-auth-rs/src/ckb_auth.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
extern crate alloc;

use crate::{CkbAuthError, CkbAuthType, CkbEntryType, EntryCategoryType};
use alloc::collections::BTreeMap;
use alloc::ffi::CString;
use alloc::format;
use alloc::vec::Vec;
use ckb_std::high_level::exec_cell;
use hex::encode;

#[cfg(feature = "ckb2023")]
use alloc::vec::Vec;
#[cfg(feature = "ckb2023")]
use ckb_std::high_level::spawn_cell;
use ckb_std::{
ckb_types::core::ScriptHashType,
dynamic_loading_c_impl::{CKBDLContext, Library, Symbol},
};
use core::mem::size_of_val;
use hex::encode;

#[cfg(feature = "enable-dynamic-library")]
use super::ckb_auth_dl::ckb_auth_dl;

pub fn ckb_auth(
entry: &CkbEntryType,
Expand All @@ -23,6 +22,7 @@ pub fn ckb_auth(
) -> Result<(), CkbAuthError> {
match entry.entry_category {
EntryCategoryType::Exec => ckb_auth_exec(entry, id, signature, message),
#[cfg(feature = "enable-dynamic-library")]
EntryCategoryType::DynamicLinking => ckb_auth_dl(entry, id, signature, message),
#[cfg(feature = "ckb2023")]
EntryCategoryType::Spawn => ckb_auth_spawn(entry, id, signature, message),
Expand Down Expand Up @@ -73,117 +73,3 @@ fn ckb_auth_exec(
exec_cell(&entry.code_hash, entry.hash_type, &args)?;
Ok(())
}

type DLContext = CKBDLContext<[u8; 512 * 1024]>;
type CkbAuthValidate = unsafe extern "C" fn(
auth_algorithm_id: u8,
signature: *const u8,
signature_size: u32,
message: *const u8,
message_size: u32,
pubkey_hash: *mut u8,
pubkey_hash_size: u32,
) -> i32;

const EXPORTED_FUNC_NAME: &str = "ckb_auth_validate";

struct CKBDLLoader {
pub context: DLContext,
pub context_used: usize,
pub loaded_lib: BTreeMap<[u8; 33], Library>,
}

static mut G_CKB_DL_LOADER: Option<CKBDLLoader> = None;
impl CKBDLLoader {
pub fn get() -> &'static mut Self {
unsafe {
match G_CKB_DL_LOADER.as_mut() {
Some(v) => v,
None => {
G_CKB_DL_LOADER = Some(Self::new());
G_CKB_DL_LOADER.as_mut().unwrap()
}
}
}
}

fn new() -> Self {
Self {
context: unsafe { DLContext::new() },
context_used: 0,
loaded_lib: BTreeMap::new(),
}
}

fn get_lib(
&mut self,
code_hash: &[u8; 32],
hash_type: ScriptHashType,
) -> Result<&Library, CkbAuthError> {
let mut lib_key = [0u8; 33];
lib_key[..32].copy_from_slice(code_hash);
lib_key[32] = hash_type as u8;

let has_lib = match self.loaded_lib.get(&lib_key) {
Some(_) => true,
None => false,
};

if !has_lib {
let size = size_of_val(&self.context);
let lib = self
.context
.load_with_offset(code_hash, hash_type, self.context_used, size)
.map_err(|_| CkbAuthError::LoadDLError)?;
self.context_used += lib.consumed_size();
self.loaded_lib.insert(lib_key.clone(), lib);
};
Ok(self.loaded_lib.get(&lib_key).unwrap())
}

pub fn get_validate_func<T>(
&mut self,
code_hash: &[u8; 32],
hash_type: ScriptHashType,
func_name: &str,
) -> Result<Symbol<T>, CkbAuthError> {
let lib = self.get_lib(code_hash, hash_type)?;

let func: Option<Symbol<T>> = unsafe { lib.get(func_name.as_bytes()) };
if func.is_none() {
return Err(CkbAuthError::LoadDLFuncError);
}
Ok(func.unwrap())
}
}

fn ckb_auth_dl(
entry: &CkbEntryType,
id: &CkbAuthType,
signature: &[u8],
message: &[u8; 32],
) -> Result<(), CkbAuthError> {
let func: Symbol<CkbAuthValidate> = CKBDLLoader::get().get_validate_func(
&entry.code_hash,
entry.hash_type,
EXPORTED_FUNC_NAME,
)?;

let mut pub_key = id.pubkey_hash.clone();
let rc_code = unsafe {
func(
id.algorithm_id.clone().into(),
signature.as_ptr(),
signature.len() as u32,
message.as_ptr(),
message.len() as u32,
pub_key.as_mut_ptr(),
pub_key.len() as u32,
)
};

match rc_code {
0 => Ok(()),
_ => Err(CkbAuthError::RunDLError),
}
}
137 changes: 137 additions & 0 deletions ckb-auth-rs/src/ckb_auth_dl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use crate::{CkbAuthError, CkbAuthType, CkbEntryType};
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use ckb_std::{
ckb_types::core::ScriptHashType,
dynamic_loading_c_impl::{CKBDLContext, Library, Symbol},
};
use core::mem::size_of;

#[cfg(feature = "dynamic-library-memory-200")]
type DLContext = CKBDLContext<[u8; 200 * 1024]>;

#[cfg(feature = "dynamic-library-memory-400")]
type DLContext = CKBDLContext<[u8; 400 * 1024]>;

#[cfg(feature = "dynamic-library-memory-600")]
type DLContext = CKBDLContext<[u8; 600 * 1024]>;

type CkbAuthValidate = unsafe extern "C" fn(
auth_algorithm_id: u8,
signature: *const u8,
signature_size: u32,
message: *const u8,
message_size: u32,
pubkey_hash: *mut u8,
pubkey_hash_size: u32,
) -> i32;

const EXPORTED_FUNC_NAME: &str = "ckb_auth_validate";

struct CKBDLLoader {
pub context: Box<DLContext>,
pub context_used: usize,
pub loaded_lib: BTreeMap<[u8; 33], Library>,
}

lazy_static::lazy_static! {
static ref G_DL_CONTEXT: DLContext = unsafe { DLContext::new() };
}

static mut G_CKB_DL_LOADER: Option<CKBDLLoader> = None;
impl CKBDLLoader {
pub fn get() -> &'static mut Self {
unsafe {
match G_CKB_DL_LOADER.as_mut() {
Some(v) => v,
None => {
G_CKB_DL_LOADER = Some(Self::new());
G_CKB_DL_LOADER.as_mut().unwrap()
}
}
}
}

fn new() -> Self {
Self {
context: unsafe {
let dl_ctx: &DLContext = &G_DL_CONTEXT;
Box::from_raw(dl_ctx as *const DLContext as *mut DLContext)
},
context_used: 0,
loaded_lib: BTreeMap::new(),
}
}

fn get_lib(
&mut self,
code_hash: &[u8; 32],
hash_type: ScriptHashType,
) -> Result<&Library, CkbAuthError> {
let mut lib_key = [0u8; 33];
lib_key[..32].copy_from_slice(code_hash);
lib_key[32] = hash_type as u8;

let has_lib = match self.loaded_lib.get(&lib_key) {
Some(_) => true,
None => false,
};

if !has_lib {
let size = size_of::<DLContext>();
let lib = self
.context
.load_with_offset(code_hash, hash_type, self.context_used, size)
.map_err(|_| CkbAuthError::LoadDLError)?;
self.context_used += lib.consumed_size();
self.loaded_lib.insert(lib_key.clone(), lib);
};
Ok(self.loaded_lib.get(&lib_key).unwrap())
}

pub fn get_validate_func<T>(
&mut self,
code_hash: &[u8; 32],
hash_type: ScriptHashType,
func_name: &str,
) -> Result<Symbol<T>, CkbAuthError> {
let lib = self.get_lib(code_hash, hash_type)?;

let func: Option<Symbol<T>> = unsafe { lib.get(func_name.as_bytes()) };
if func.is_none() {
return Err(CkbAuthError::LoadDLFuncError);
}
Ok(func.unwrap())
}
}

pub fn ckb_auth_dl(
entry: &CkbEntryType,
id: &CkbAuthType,
signature: &[u8],
message: &[u8; 32],
) -> Result<(), CkbAuthError> {
let func: Symbol<CkbAuthValidate> = CKBDLLoader::get().get_validate_func(
&entry.code_hash,
entry.hash_type,
EXPORTED_FUNC_NAME,
)?;

let mut pub_key = id.pubkey_hash.clone();
let rc_code = unsafe {
func(
id.algorithm_id.clone().into(),
signature.as_ptr(),
signature.len() as u32,
message.as_ptr(),
message.len() as u32,
pub_key.as_mut_ptr(),
pub_key.len() as u32,
)
};

match rc_code {
0 => Ok(()),
_ => Err(CkbAuthError::RunDLError),
}
}
8 changes: 7 additions & 1 deletion ckb-auth-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ mod ckb_auth;
#[cfg(target_arch = "riscv64")]
pub use ckb_auth::ckb_auth;

#[cfg(all(feature = "enable-dynamic-library", target_arch = "riscv64"))]
mod ckb_auth_dl;

#[cfg(target_arch = "riscv64")]
mod generate_sighash_all;

Expand Down Expand Up @@ -54,7 +57,7 @@ impl TryFrom<u8> for AuthAlgorithmIdType {
type Error = CkbAuthError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
if (value >= AuthAlgorithmIdType::Ckb.into()
&& value <= AuthAlgorithmIdType::Iso97962.into())
&& value <= AuthAlgorithmIdType::Secp256r1.into())
|| value == AuthAlgorithmIdType::OwnerLock.into()
{
Ok(unsafe { transmute(value) })
Expand All @@ -75,6 +78,7 @@ pub enum CkbAuthError {
SignatureMissing,
EncodeArgs,
GenerateSigHash,
UnsupportEntryType,
}

#[cfg(target_arch = "riscv64")]
Expand All @@ -94,6 +98,7 @@ impl From<NulError> for CkbAuthError {
#[derive(Clone)]
pub enum EntryCategoryType {
Exec = 0,
#[cfg(feature = "enable-dynamic-library")]
DynamicLinking = 1,
#[cfg(feature = "ckb2023")]
Spawn = 2,
Expand All @@ -104,6 +109,7 @@ impl TryFrom<u8> for EntryCategoryType {
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Exec),
#[cfg(feature = "enable-dynamic-library")]
1 => Ok(Self::DynamicLinking),
#[cfg(feature = "ckb2023")]
2 => Ok(Self::Spawn),
Expand Down
Loading
Loading