Skip to content

Commit 89efc3b

Browse files
feat: add C version of CPI program (#6)
* feat: add C CPI program * add forgotten CI step & more comments
1 parent 6071b5c commit 89efc3b

File tree

5 files changed

+105
-2
lines changed

5 files changed

+105
-2
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
name: Run tests against C implementations
8181
strategy:
8282
matrix:
83-
program: [helloworld, transfer-lamports]
83+
program: [helloworld, transfer-lamports, cpi]
8484
fail-fast: false
8585
runs-on: ubuntu-latest
8686
steps:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,4 @@ the address and `invoke_signed` to CPI to the system program.
181181
| --- | --- |
182182
| Rust | 3662 |
183183
| Zig | 3141 |
184+
| C | 3122 |

cpi/c/Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
LOCAL_PATH := ../../solana-c-sdk/c/
2+
3+
.PHONY: all clean
4+
5+
SRC_DIR ?= ./src
6+
OUT_DIR ?= ./out
7+
8+
all: $(OUT_DIR)/solana_program_rosetta_cpi.so
9+
10+
clean:
11+
rm -rf $(OUT_DIR)
12+
13+
LLVM_DIR = $(LOCAL_PATH)../dependencies/platform-tools/llvm
14+
LLVM_SYSTEM_INC_DIRS := $(LLVM_DIR)/lib/clang/17/include
15+
STD_INC_DIRS := $(LLVM_DIR)/include
16+
STD_LIB_DIRS := $(LLVM_DIR)/lib
17+
18+
CC := $(LLVM_DIR)/bin/clang
19+
LLD := $(LLVM_DIR)/bin/ld.lld
20+
21+
SYSTEM_INC_DIRS := \
22+
$(LOCAL_PATH)inc \
23+
$(LLVM_SYSTEM_INC_DIRS) \
24+
25+
C_FLAGS := \
26+
-Werror \
27+
-O2 \
28+
-fno-builtin \
29+
-std=c17 \
30+
$(addprefix -isystem,$(SYSTEM_INC_DIRS)) \
31+
$(addprefix -I,$(STD_INC_DIRS)) \
32+
-target sbf \
33+
-fPIC
34+
35+
SBF_LLD_FLAGS := \
36+
-z notext \
37+
-shared \
38+
--Bdynamic \
39+
$(LOCAL_PATH)sbf.ld \
40+
--entry entrypoint \
41+
-L $(STD_LIB_DIRS) \
42+
-lc \
43+
44+
$(OUT_DIR)/main.o: $(SRC_DIR)/main.c
45+
mkdir -p $(OUT_DIR)
46+
$(CC) $(C_FLAGS) -o $(OUT_DIR)/main.o -c $(SRC_DIR)/main.c
47+
48+
$(OUT_DIR)/solana_program_rosetta_cpi.so: $(OUT_DIR)/main.o
49+
$(LLD) $(SBF_LLD_FLAGS) -o $(OUT_DIR)/solana_program_rosetta_cpi.so $(OUT_DIR)/main.o

cpi/c/src/main.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @brief C-based CPI BPF program
3+
*/
4+
#include <solana_sdk.h>
5+
6+
/// Amount of bytes of account data to allocate
7+
#define SIZE 42
8+
9+
extern uint64_t entrypoint(const uint8_t *input)
10+
{
11+
SolAccountInfo accounts[2];
12+
SolParameters params = (SolParameters){.ka = accounts};
13+
14+
if (!sol_deserialize(input, &params, SOL_ARRAY_SIZE(accounts)))
15+
{
16+
return ERROR_INVALID_ARGUMENT;
17+
}
18+
19+
SolAccountInfo allocated_info = params.ka[0];
20+
SolAccountInfo system_program_info = params.ka[1];
21+
22+
uint8_t seed[] = {'Y', 'o', 'u', ' ', 'p', 'a', 's', 's',
23+
' ', 'b', 'u', 't', 't', 'e', 'r'};
24+
const SolSignerSeed seeds[] = {{seed, SOL_ARRAY_SIZE(seed)},
25+
{&params.data[0], 1}};
26+
27+
const SolSignerSeeds signers_seeds[] = {{seeds, SOL_ARRAY_SIZE(seeds)}};
28+
29+
SolPubkey expected_allocated_key;
30+
if (SUCCESS != sol_create_program_address(seeds, SOL_ARRAY_SIZE(seeds),
31+
params.program_id,
32+
&expected_allocated_key))
33+
{
34+
return ERROR_INVALID_INSTRUCTION_DATA;
35+
}
36+
37+
// allocated key does not match the derived address
38+
if (!SolPubkey_same(&expected_allocated_key, allocated_info.key))
39+
{
40+
return ERROR_INVALID_ARGUMENT;
41+
}
42+
43+
SolAccountMeta arguments[] = {{allocated_info.key, true, true}};
44+
uint8_t data[4 + 8]; // Enough room for the Allocate instruction
45+
*(uint16_t *)data = 8; // Allocate instruction enum value
46+
*(uint64_t *)(data + 4) = SIZE; // Size to allocate
47+
const SolInstruction instruction = {system_program_info.key, arguments,
48+
SOL_ARRAY_SIZE(arguments), data,
49+
SOL_ARRAY_SIZE(data)};
50+
51+
return sol_invoke_signed(&instruction, params.ka, params.ka_num,
52+
signers_seeds, SOL_ARRAY_SIZE(signers_seeds));
53+
}

transfer-lamports/c/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @brief C-based Helloworld BPF program
2+
* @brief C-based Transfer Lamports BPF program
33
*/
44
#include <solana_sdk.h>
55

0 commit comments

Comments
 (0)