Mô hình chi phí CPI và đồng bộ dữ liệu

Tóm tắt

Mỗi CPI tốn ~1.000 CU cơ bản cộng với chi phí serialization. Dữ liệu tài khoản được đồng bộ trước và sau khi thực thi callee. Ký PDA sử dụng program ID của caller. Dữ liệu trả về giới hạn ở 1.024 byte.

Mô hình chi phí CPI

Chi phí CPI được trừ từ cùng một ngân sách tính toán giao dịch (đồng hồ đo chung). Công thức chi phí đầy đủ cho mỗi lần gọi invoke / invoke_signed:

total_cpi_cost = invocation_cost
+ instruction_data_cost
+ account_meta_cost (SIMD-0339 only)
+ account_info_cost (SIMD-0339 only)
+ per_account_data_cost (for each non-executable account)
+ callee_execution_cost

Phân tích chi phí

Thành phần chi phíCông thứcNguồn
Invocation (cố định)invoke_units = 1.000 CU (946 với SIMD-0339)Tính phí tại điểm vào CPI
Serialization instruction datainstruction_data_len / cpi_bytes_per_unitcpi_bytes_per_unit = 250. Tính phí trong translate_instruction.
Serialization account meta (SIMD-0339)(num_account_metas * 34) / cpi_bytes_per_unitMỗi AccountMeta là 34 byte (32 pubkey + 1 is_signer + 1 is_writable). Tính phí trong translate_instruction.
Translation account info (SIMD-0339)(num_account_infos * 80) / cpi_bytes_per_unitACCOUNT_INFO_BYTE_SIZE = 80 byte (32 key + 32 owner + 8 lamports + 8 data_len). Tính phí trong translate_account_infos.
Dữ liệu theo từng tài khoảnaccount_data_len / cpi_bytes_per_unitTính phí cho mỗi tài khoản trong CallerAccount::from_account_info và cho tài khoản executable.
Thực thi calleeBất kỳ CU nào mà chương trình callee tiêu thụTrừ từ đồng hồ đo chung trong quá trình thực thi callee.

Ví dụ tính toán chi phí

Một CPI với 100 byte instruction data, 5 account meta, 5 account info (mỗi cái có 1.000 byte dữ liệu), SIMD-0339 đang hoạt động:

invocation_cost = 946
instruction_data_cost = 100 / 250 = 0 (integer division)
account_meta_cost = (5 * 34) / 250 = 0
account_info_cost = (5 * 80) / 250 = 1
per_account_data_cost = 5 * (1000 / 250) = 20
total (before callee) = 967 CUs

Đồng bộ hóa dữ liệu tài khoản

Trạng thái tài khoản được đồng bộ hóa giữa caller và callee tại hai thời điểm trong quá trình CPI. Điều này đảm bảo cả hai bên đều thấy một cái nhìn nhất quán về dữ liệu tài khoản.

Đồng bộ trước CPI (caller sang callee)

Trước khi callee thực thi, update_callee_account sao chép các thay đổi đang diễn ra của caller sang chế độ xem tài khoản của callee:

TrườngHướngKhi nào
LamportsCaller -> CalleeNếu giá trị khác với chế độ xem hiện tại của callee
Độ dài dataCaller -> CalleeNếu caller đã thay đổi kích thước tài khoản. Không được vượt quá original_data_len + MAX_PERMITTED_DATA_INCREASE (10 KiB).
Nội dung dataCaller -> CalleeNếu data của tài khoản có thể sửa đổi (can_data_be_changed thành công)
OwnerCaller -> CalleeĐược đặt cuối cùng, để các thay đổi data/lamport được phép dưới owner cũ

Đồng bộ sau CPI (callee sang caller)

Sau khi callee trả về, update_caller_account sao chép các thay đổi của callee trở lại chế độ xem của caller. Điều này chỉ chạy cho các tài khoản được đánh dấu là writable:

TrườngHướngKhi nào
LamportsCallee -> CallerLuôn được sao chép lại
OwnerCallee -> CallerLuôn được sao chép lại
Độ dài dataCallee -> CallerNếu có thay đổi. Con trỏ data slice của VM và trường độ dài serialized được cập nhật. Nếu tài khoản bị thu nhỏ, bộ nhớ được giải phóng sẽ được đặt về zero. Nếu độ dài mới vượt quá original_data_len + MAX_PERMITTED_DATA_INCREASE, trả về InvalidRealloc.
Nội dung dataCallee -> CallerĐược sao chép từ data buffer của callee sang vùng data serialized của caller

Giới hạn realloc

Dữ liệu tài khoản có thể được thay đổi kích thước trong CPI lên đến MAX_PERMITTED_DATA_INCREASE = 10.240 byte (10 KiB) vượt quá độ dài dữ liệu của tài khoản tại thời điểm bắt đầu lệnh cấp cao nhất hiện tại. Giới hạn này được thực thi trong cả update_callee_account (trước CPI) và update_caller_account (sau CPI). Vượt quá giới hạn này sẽ trả về InvalidRealloc.

Ký PDA

Khi invoke_signed được gọi, runtime sẽ suy ra địa chỉ PDA từ các seed được cung cấp và program ID của caller. Điều này xảy ra trong translate_signers_rust:

  1. Mảng signer seed được xác thực: tối đa MAX_SIGNERS (16) bộ signer seed.
  2. Mỗi bộ seed được xác thực: tối đa MAX_SEEDS (16) seed trên mỗi bộ, mỗi seed tối đa MAX_SEED_LEN (32) byte.
  3. Pubkey::create_program_address được gọi với các seed và program ID của caller (không phải của callee).
  4. Nếu các seed không tạo ra PDA hợp lệ (tức là điểm kết quả nằm trên đường cong ed25519), CPI sẽ thất bại với BadSeeds.
  5. Các pubkey PDA được suy ra sẽ được thu thập và truyền đến prepare_next_instruction như các signer hợp lệ. Trong quá trình kiểm tra đặc quyền, nếu một tài khoản callee được đánh dấu là signer và pubkey của nó khớp với một trong các PDA được suy ra này, kiểm tra signer sẽ thành công.

PDA được suy ra bằng program ID của caller, không phải của callee. Điều này có nghĩa là chỉ chương trình sở hữu PDA (chương trình có ID được sử dụng để suy ra nó) mới có thể ký thay mặt cho nó. Một chương trình không thể ký cho các PDA được suy ra từ các chương trình khác.

Dữ liệu trả về

Các chương trình có thể truyền dữ liệu trả lại cho caller bằng cách sử dụng cơ chế return data. Điều này sử dụng hai syscall:

  • sol_set_return_data: Thiết lập tối đa MAX_RETURN_DATA (1.024) byte dữ liệu trả về cho lệnh hiện tại. Chi phí là data_len / cpi_bytes_per_unit + syscall_base_cost CU.
  • sol_get_return_data: Đọc dữ liệu trả về được thiết lập bởi lệnh được thực thi gần đây nhất. Trả về dữ liệu cùng với program ID đã thiết lập nó. Chi phí là (data_len + 32) / cpi_bytes_per_unit + syscall_base_cost CU (32 byte cho program ID).

Dữ liệu trả về được lưu trữ theo từng giao dịch và bị ghi đè bởi mỗi lệnh gọi sol_set_return_data. Khi bắt đầu mỗi lần gọi chương trình, runtime đặt lại dữ liệu trả về thành rỗng. Sau khi CPI trả về, bên gọi có thể đọc bất kỳ dữ liệu trả về nào mà bên được gọi (hoặc bất kỳ chương trình nào mà bên được gọi đã gọi) đặt cuối cùng.

Dữ liệu trả về bị giới hạn ở 1.024 byte. Chỉ chương trình cuối cùng gọi sol_set_return_data trong chuỗi gọi mới quyết định những gì bên gọi nhìn thấy. Nếu bên được gọi thực hiện thêm các CPI đặt dữ liệu trả về, dữ liệu trả về của chính bên được gọi sẽ bị ghi đè.

Is this page helpful?

Mục lục

Chỉnh sửa trang

Quản lý bởi

© 2026 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối