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 package cầ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ằnginput.chain == "ethereum"
!=Không bằnginput.chain != "polygon"
>Lớn hơninput.usd_value > 1000
>=Lớn hơn hoặc bằnginput.usd_value >= 1000
<Nhỏ hơninput.usd_value < 100
<=Nhỏ hơn hoặc bằnginput.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ộnginput.usd_value + 100
-Trừinput.usd_value - fees
*Nhâninput.usd_value * 1.1
/Chiainput.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 denydenyGasSponsor, 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àmMô TảTrả Về
contains(string, substring)Kiểm tra xem chuỗi có chứa chuỗi con khôngboolean
startswith(string, prefix)Kiểm tra xem chuỗi có bắt đầu bằng tiền tố khôngboolean
endswith(string, suffix)Kiểm tra xem chuỗi có kết thúc bằng hậu tố khôngboolean
lower(string)Chuyển đổi thành chữ thườngstring
upper(string)Chuyển đổi thành chữ hoastring
substring(string, start, length)Trích xuất phần của chuỗistring
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àmMô 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 arrayKiểm tra xem giá trị có tồn tại trong mảng khôngboolean

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
}
Tài Liệu Tham Khảo Ngôn Ngữ | 256 Blocks