Tài Liệu Tham Khảo Ngôn Ngữ
Hướng dẫn đầy đủ về cú pháp Rego và các tính năng ngôn ngữ để viết chính sách
Các chính sách được viết bằng Rego, một ngôn ngữ chính sách khai báo được thiết kế để thể hiện các quyết định kiểm soát truy cập phức tạp. Không giống như các ngôn ngữ mệnh lệnh, nơi bạn mô tả cách tính toán kết quả, Rego cho phép bạn mô tả những điều kiện nào sẽ kích hoạt quyết định chính sách. Trang này bao gồm tất cả cú pháp và các tính năng ngôn ngữ được hỗ trợ trong 256 Blocks.
Cấu Trúc Chính Sách
Mỗi chính sách bạn viết được 256 Blocks tự động bao bọc với mã soạn sẵn cần thiết. Điều này có nghĩa là bạn có thể tập trung hoàn toàn vào việc viết các quy tắc mà không cần lo lắng về các khai báo gói hoặc giá trị mặc định.
Tất cả các chính sách:
- Được tự động bao bọc với câu lệnh
packagecần thiết - Có sẵn
default deny := false(cho phép theo mặc định) - Có sẵn
default denyGasSponsor := false(tài trợ theo mặc định) - Chỉ có thể định nghĩa quy tắc, không ghi đè các giá trị mặc định
Cú Pháp Quy Tắc Cơ Bản
Quy tắc là các khối xây dựng của chính sách. Một quy tắc bao gồm phần đầu (tên quy tắc, ví dụ: deny hoặc denyGasSponsor) và phần thân (các điều kiện). Khi tất cả các điều kiện trong phần thân đều đúng, quy tắc được đánh giá là true.
Ví dụ
# Basic structure: rule_name if { conditions }
deny if {
input.usd_value > 10000
}Nhiều Điều Kiện (Logic AND)
Khi bạn bao gồm nhiều điều kiện trong cùng một phần thân quy tắc, TẤT CẢ các điều kiện phải đúng để quy tắc được kích hoạt. Mỗi điều kiện được kết hợp ngầm định với AND.
Ví dụ
# Both conditions must be true to deny
deny if {
input.chain == "ethereum"
input.usd_value > 1000
}Nhiều Quy Tắc (Logic OR)
Khi bạn định nghĩa nhiều quy tắc với cùng tên, BẤT KỲ quy tắc nào khớp sẽ kích hoạt chính sách. Điều này cung cấp logic OR giữa các quy tắc.
Ví dụ
# Either condition triggers denial
deny if {
input.chain == "ethereum"
}
deny if {
input.usd_value > 10000
}Kết Hợp AND và OR
Bạn có thể kết hợp cả hai mẫu cho logic phức tạp. Mỗi phần thân quy tắc sử dụng logic AND nội bộ, trong khi nhiều quy tắc cung cấp logic OR giữa chúng.
Ví dụ
# Deny if: (ethereum AND high-value) OR (any chain AND blocked country)
deny if {
input.chain == "ethereum"
input.usd_value > 5000
}
deny if {
input.source_country in {"KP", "IR", "CU"}
}Gán Biến
Sử dụng toán tử := để gán giá trị cho biến. Các biến làm cho chính sách của bạn dễ đọc và duy trì hơn bằng cách đặt tên có ý nghĩa cho các giá trị và cho phép tái sử dụng.
Biến Cấp Chính Sách
Các biến được định nghĩa bên ngoài phần thân quy tắc hoạt động như các hằng số có thể được tham chiếu bởi nhiều quy tắc. Sử dụng chúng cho ngưỡng, danh sách cho phép và danh sách chặn.
Ví dụ
# Policy-level constants - defined once, used everywhere
max_transaction_value := 50000
blocked_countries := {"KP", "IR", "CU", "SY"}
approved_senders := {"0x742d35cc...", "0xa0b86991..."}
deny if {
input.usd_value > max_transaction_value
}
deny if {
input.source_country in blocked_countries
}
deny if {
not input.from_address in approved_senders
}Biến Cục Bộ
Các biến được định nghĩa bên trong phần thân quy tắc là cục bộ cho quy tắc đó. Sử dụng chúng cho các phép tính trung gian hoặc để cải thiện khả năng đọc.
Ví dụ
deny if {
# Calculate with a safety margin
value_with_buffer := input.usd_value * 1.15
value_with_buffer > 10000
}
deny if {
# Estimate gas cost in wei
gas_cost := to_number(input.gas_limit) * to_number(input.max_fee_per_gas)
gas_cost > 1000000000000000000 # 1 ETH in wei
}Toán Tử So Sánh
Rego cung cấp các toán tử so sánh tiêu chuẩn để đánh giá điều kiện. Chúng hoạt động với chuỗi, số và các kiểu có thể so sánh khác.
| Toán Tử | Mô Tả | Ví Dụ |
|---|---|---|
== | Bằng | input.chain == "ethereum" |
!= | Không bằng | input.chain != "polygon" |
> | Lớn hơn | input.usd_value > 1000 |
>= | Lớn hơn hoặc bằng | input.usd_value >= 1000 |
< | Nhỏ hơn | input.usd_value < 100 |
<= | Nhỏ hơn hoặc bằng | input.usd_value <= 100 |
Ví dụ
# Block high-value transactions on expensive chains
deny if {
input.chain == "ethereum"
input.usd_value >= 5000
}
# Block transactions below a minimum value (potential spam)
deny if {
input.usd_value != null
input.usd_value < 1
}Toán Tử Số Học
Bạn có thể thực hiện các phép tính số học trong các điều kiện chính sách của mình. Điều này hữu ích để tính toán ngưỡng, áp dụng hệ số nhân hoặc kết hợp các giá trị.
| Toán Tử | Mô Tả | Ví Dụ |
|---|---|---|
+ | Cộng | input.usd_value + 100 |
- | Trừ | input.usd_value - fees |
* | Nhân | input.usd_value * 1.1 |
/ | Chia | input.usd_value / 2 |
% | Modulo (số dư) | input.gas_limit % 1000 |
Ví dụ
# Apply a 10% buffer when checking limits
deny if {
input.usd_value * 1.1 > 10000
}
# Block if combined value exceeds threshold
deny if {
total := input.usd_value + 500 # Add estimated fees
total > 5000
}Toán Tử Logic
Ngoài AND ngầm định (nhiều điều kiện) và OR (nhiều quy tắc), Rego cung cấp các toán tử logic tường minh cho các biểu thức phức tạp hơn.
Toán Tử not
Sử dụng not để phủ định một điều kiện. Điều này đặc biệt hữu ích cho các mẫu danh sách cho phép nơi bạn muốn từ chối bất cứ thứ gì KHÔNG có trong tập hợp được phép.
Ví dụ
# Only allow specific chains (deny everything else)
allowed_chains := {"polygon", "base", "arbitrum"}
deny if {
not input.chain in allowed_chains
}Ví dụ: Kết Hợp với Các Điều Kiện Khác
# Deny if NOT a read-only method AND value is high
deny if {
not input.rpc_method in {"eth_call", "eth_getBalance"}
input.usd_value > 1000
}Quy Tắc Trợ Giúp
Ngoài deny và denyGasSponsor, bạn có thể định nghĩa các quy tắc tùy chỉnh của riêng mình để tổ chức logic phức tạp. Các quy tắc trợ giúp hoạt động như các khối xây dựng có thể tái sử dụng giúp chính sách của bạn dễ đọc và duy trì hơn.
Quy tắc trợ giúp đơn giản là một điều kiện có tên được đánh giá là true khi phần thân của nó khớp. Sau đó, bạn có thể tham chiếu các quy tắc này trong quy tắc deny hoặc denyGasSponsor của mình, bao gồm cả toán tử not để phủ định chúng.
Ví dụ
# Define a helper rule to check if request is from a trusted source
is_trusted if {
input.source_country in {"US", "GB", "DE"}
input.source_ip in {"203.0.113.10", "203.0.113.11"}
}
# Define another helper for high-risk transactions
is_high_risk if {
input.usd_value > 10000
}
is_high_risk if {
input.source_country in {"RU", "CN"}
}
# Use helper rules in deny conditions
deny if {
not is_trusted
is_high_risk
}Các quy tắc trợ giúp đặc biệt hữu ích cho:
- Khả năng tái sử dụng: Định nghĩa điều kiện một lần, sử dụng trong nhiều quy tắc
- Khả năng đọc: Đặt tên có ý nghĩa cho các điều kiện phức tạp
- Phủ định: Sử dụng
notđể kiểm tra khi điều kiện KHÔNG được đáp ứng - Tổ chức: Chia nhỏ các chính sách phức tạp thành các thành phần logic
Thao Tác Chuỗi
Chuỗi là các chuỗi ký tự được đặt trong dấu ngoặc kép (""). Hầu hết các trường đầu vào như input.chain, input.rpc_method và địa chỉ đều là chuỗi. Rego cung cấp nhiều hàm tích hợp để làm việc với chuỗi, cần thiết cho việc khớp mẫu trên địa chỉ, tên phương thức và các trường văn bản khác.
| Hàm | Mô Tả | Trả Về |
|---|---|---|
contains(string, substring) | Kiểm tra xem chuỗi có chứa chuỗi con không | boolean |
startswith(string, prefix) | Kiểm tra xem chuỗi có bắt đầu bằng tiền tố không | boolean |
endswith(string, suffix) | Kiểm tra xem chuỗi có kết thúc bằng hậu tố không | boolean |
lower(string) | Chuyển đổi thành chữ thường | string |
upper(string) | Chuyển đổi thành chữ hoa | string |
substring(string, start, length) | Trích xuất phần của chuỗi | string |
sprintf(format, values) | Định dạng chuỗi với các giá trị | string |
Ví dụ
# Block any method containing "sign" (covers eth_sign, personal_sign, etc.)
deny if {
contains(input.rpc_method, "sign")
}
# Block addresses starting with known malicious prefix
deny if {
startswith(lower(input.to_address), "0x000000000000000000000000000000000000dead")
}
# Block debug and admin methods
deny if {
startswith(input.rpc_method, "debug_")
}
deny if {
startswith(input.rpc_method, "admin_")
}Thao Tác Mảng
Mảng là danh sách có thứ tự các giá trị, được định nghĩa bằng dấu ngoặc vuông []. Không giống như tập hợp, mảng bảo toàn thứ tự của các phần tử và có thể chứa các bản sao. Bạn sẽ thường xuyên làm việc với mảng trong chính sách, đặc biệt là input.contract_addresses chứa tất cả các địa chỉ hợp đồng liên quan đến một yêu cầu.
# Array syntax
my_array := ["first", "second", "third"]Rego cung cấp nhiều cách để kiểm tra và làm việc với mảng.
| Hàm | Mô Tả | Trả Về |
|---|---|---|
count(array) | Số lượng phần tử | number |
array[index] | Truy cập phần tử theo chỉ mục (bắt đầu từ 0) | element |
value in array | Kiểm tra xem giá trị có tồn tại trong mảng không | boolean |
Ví dụ
# Limit the number of contracts in a single request
deny if {
count(input.contract_addresses) > 10
}
# Check if a specific address is in the contract list
deny if {
"0xbanned..." in input.contract_addresses
}
# Access specific array elements
deny if {
count(input.contract_addresses) > 0
first_contract := input.contract_addresses[0]
startswith(first_contract, "0xdead")
}Kiểm Tra Thành Viên
Kiểm tra thành viên là một trong những thao tác phổ biến nhất trong chính sách. Bạn sẽ sử dụng nó để kiểm tra xem các giá trị có thuộc danh sách cho phép, danh sách chặn hoặc các tập hợp giá trị được phép khác không.
Tập Hợp
Tập hợp là các bộ sưu tập không có thứ tự của các giá trị duy nhất, được định nghĩa bằng dấu ngoặc nhọn {}. Sử dụng toán tử in để kiểm tra xem một giá trị có tồn tại trong tập hợp không.
# Set syntax
my_set := {"value1", "value2", "value3"}Tập hợp được tối ưu hóa cho kiểm tra thành viên nhanh, làm cho chúng lý tưởng cho danh sách cho phép và danh sách chặn.
Ví dụ
# Block requests from sanctioned countries
blocked_countries := {"KP", "IR", "CU", "SY", "RU"}
deny if {
input.source_country in blocked_countries
}
# Only allow specific chains
allowed_chains := {"polygon", "base", "arbitrum"}
deny if {
not input.chain in allowed_chains
}Tập Hợp Nội Tuyến vs Tập Hợp Có Tên
Bạn có thể định nghĩa tập hợp nội tuyến trong các quy tắc hoặc như các biến có tên ở cấp độ chính sách. Các tập hợp có tên cải thiện khả năng đọc và cho phép tái sử dụng trong nhiều quy tắc.
Ví dụ
# Inline set - good for simple, one-off checks
deny if {
input.rpc_method in {"eth_sign", "personal_sign", "eth_signTypedData"}
}
# Named set - better for reusability and readability
approved_contracts := {
"0xdac17f958d2ee523a2206206994597c13d831ec7", # USDT
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", # USDC
"0x6b175474e89094c44da98b954eedeac495271d0f" # DAI
}
deny if {
some addr in input.contract_addresses
not addr in approved_contracts
}Lặp với some
Từ khóa some cho phép bạn lặp qua các bộ sưu tập và kiểm tra điều kiện đối với mỗi phần tử. Điều này rất cần thiết khi làm việc với các mảng như input.contract_addresses.
Lặp Cơ Bản
Sử dụng some để kiểm tra xem BẤT KỲ phần tử nào trong bộ sưu tập có khớp với điều kiện không.
Ví dụ
# Deny if ANY contract address is in the blocklist
blocked_contracts := {"0xbanned1...", "0xbanned2..."}
deny if {
some addr in input.contract_addresses
addr in blocked_contracts
}Lặp với Chỉ Mục
Bạn cũng có thể truy cập chỉ mục của mỗi phần tử trong quá trình lặp.
Ví dụ
# Check conditions on specific positions
deny if {
some i, addr in input.contract_addresses
i == 0 # First contract only
startswith(addr, "0x000")
}Ví dụ: Tìm Bất Kỳ Khớp Nào
# Deny if any contract starts with a suspicious prefix
deny if {
some addr in input.contract_addresses
startswith(lower(addr), "0x000000000000000000000000")
}
# Deny if any contract is not in the approved list
approved := {"0xusdt...", "0xusdc...", "0xdai..."}
deny if {
some addr in input.contract_addresses
not addr in approved
}Lặp với every
Trong khi some kiểm tra xem BẤT KỲ phần tử nào khớp, every yêu cầu TẤT CẢ các phần tử khớp với một điều kiện. Điều này hữu ích để đảm bảo toàn bộ bộ sưu tập đáp ứng tiêu chí của bạn.
Ví dụ
# Deny only if ALL contracts are from a suspicious set
# (unlikely to be legitimate if every address is suspicious)
suspicious_prefixes := {"0x0000000000000000"}
deny if {
count(input.contract_addresses) > 0
every addr in input.contract_addresses {
some prefix in suspicious_prefixes
startswith(addr, prefix)
}
}Ví dụ: Mẫu Xác Thực
# Ensure all contracts are from approved list (inverse of some/not)
approved_contracts := {"0xusdt...", "0xusdc...", "0xdai..."}
# This denies if ANY contract is not approved
deny if {
some addr in input.contract_addresses
not addr in approved_contracts
}
# Equivalent using every (deny if NOT every contract is approved)
deny if {
count(input.contract_addresses) > 0
not every addr in input.contract_addresses {
addr in approved_contracts
}
}Comprehension
Comprehension cho phép bạn tạo các bộ sưu tập mới bằng cách chuyển đổi hoặc lọc các bộ sưu tập hiện có. Chúng hữu ích để trích xuất các giá trị cụ thể hoặc xây dựng các tập dữ liệu dẫn xuất.
Array Comprehension
Tạo một mảng mới từ các phần tử khớp với tiêu chí nhất định.
Ví dụ
# Extract all contract addresses that start with a specific prefix
matching_contracts := [addr |
some addr in input.contract_addresses
startswith(addr, "0xa")
]
deny if {
count(matching_contracts) > 3
}Set Comprehension
Tạo một tập hợp các giá trị duy nhất.
Ví dụ
# Get unique prefixes from all contract addresses
contract_prefixes := {substring(addr, 0, 6) |
some addr in input.contract_addresses
}
# Deny if there are too many different contract prefixes (suspicious)
deny if {
count(contract_prefixes) > 5
}Else Có Điều Kiện
Từ khóa else cho phép bạn định nghĩa các giá trị dự phòng khi điều kiện không được đáp ứng. Điều này hữu ích để tính toán các giá trị dẫn xuất thay đổi dựa trên đầu vào.
Ví dụ
# Assign risk level based on transaction value
risk_level := "critical" if {
input.usd_value > 100000
} else := "high" if {
input.usd_value > 10000
} else := "medium" if {
input.usd_value > 1000
} else := "low"
# Use the computed risk level in deny rules
deny if {
risk_level == "critical"
}
denyGasSponsor if {
risk_level in {"high", "critical"}
}Ví dụ: Ngưỡng Cụ Thể Cho Từng Chuỗi
# Different limits for different chains
chain_limit := 1000 if {
input.chain == "ethereum"
} else := 5000 if {
input.chain == "polygon"
} else := 10000
deny if {
input.usd_value > chain_limit
}