11use crate :: { ckb_constants:: * , error:: SysError } ;
2+ use cstr_core:: CStr ;
23
34#[ cfg( target_arch = "riscv64" ) ]
45#[ link( name = "ckb-syscall" ) ]
@@ -7,8 +8,17 @@ extern "C" {
78}
89
910#[ cfg( not( target_arch = "riscv64" ) ) ]
10- fn syscall ( a0 : u64 , a1 : u64 , a2 : u64 , a3 : u64 , a4 : u64 , a5 : u64 , a6 : u64 , a7 : u64 ) -> u64 {
11- return u64:: MAX ;
11+ unsafe fn syscall (
12+ _a0 : u64 ,
13+ _a1 : u64 ,
14+ _a2 : u64 ,
15+ _a3 : u64 ,
16+ _a4 : u64 ,
17+ _a5 : u64 ,
18+ _a6 : u64 ,
19+ _a7 : u64 ,
20+ ) -> u64 {
21+ u64:: MAX
1222}
1323
1424/// Exit, this script will be terminated after the exit syscall.
@@ -480,3 +490,74 @@ pub fn load_cell_code(
480490 } ;
481491 SysError :: build_syscall_result ( ret, len, len)
482492}
493+
494+ /// *VM version* syscall returns current running VM version, so far 2 values will be returned:
495+ /// - Error for Lina CKB-VM version
496+ /// - 1 for the new hardfork CKB-VM version.
497+ ///
498+ /// This syscall consumes 500 cycles.
499+ pub fn vm_version ( ) -> Result < u64 , SysError > {
500+ let ret = unsafe { syscall ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , SYS_VM_VERSION ) } ;
501+ if ret == 1 {
502+ Ok ( 1 )
503+ } else {
504+ Err ( SysError :: Unknown ( ret) )
505+ }
506+ }
507+
508+ /// *Current Cycles* returns current cycle consumption just before executing this syscall.
509+ /// This syscall consumes 500 cycles.
510+ pub fn current_cycles ( ) -> u64 {
511+ unsafe { syscall ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , SYS_CURRENT_CYCLES ) }
512+ }
513+
514+ /// Exec runs an executable file from specified cell data in the context of an
515+ /// already existing machine, replacing the previous executable. The used cycles
516+ /// does not change, but the code, registers and memory of the vm are replaced
517+ /// by those of the new program. It's cycles consumption consists of two parts:
518+ ///
519+ /// - Fixed 500 cycles
520+ /// - Initial Loading Cycles (https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0014-vm-cycle-limits/0014-vm-cycle-limits.md)
521+ ///
522+ /// The arguments used here are:
523+ ///
524+ /// * `index`: an index value denoting the index of entries to read.
525+ /// * `source`: a flag denoting the source of cells or witnesses to locate, possible values include:
526+ /// + 1: input cells.
527+ /// + `0x0100000000000001`: input cells with the same running script as current script
528+ /// + 2: output cells.
529+ /// + `0x0100000000000002`: output cells with the same running script as current script
530+ /// + 3: dep cells.
531+ /// * `place`: A value of 0 or 1:
532+ /// + 0: read from cell data
533+ /// + 1: read from witness
534+ /// * `bounds`: high 32 bits means `offset`, low 32 bits means `length`. if `length` equals to zero, it read to end instead of reading 0 bytes.
535+ /// * `argc`: argc contains the number of arguments passed to the program
536+ /// * `argv`: argv is a one-dimensional array of strings
537+ pub fn exec (
538+ index : usize ,
539+ source : Source ,
540+ place : usize ,
541+ bounds : usize ,
542+ // argc: i32,
543+ argv : & [ & CStr ] ,
544+ ) -> u64 {
545+ // https://www.gnu.org/software/libc/manual/html_node/Program-Arguments.html
546+ let argc = argv. len ( ) ;
547+ let mut argv_ptr = alloc:: vec![ core:: ptr:: null( ) ; argc + 1 ] ;
548+ for ( idx, cstr) in argv. into_iter ( ) . enumerate ( ) {
549+ argv_ptr[ idx] = cstr. as_ptr ( ) ;
550+ }
551+ unsafe {
552+ syscall (
553+ index as u64 ,
554+ source as u64 ,
555+ place as u64 ,
556+ bounds as u64 ,
557+ argc as u64 ,
558+ argv_ptr. as_ptr ( ) as u64 ,
559+ 0 ,
560+ SYS_EXEC ,
561+ )
562+ }
563+ }
0 commit comments