字节码库允许对合约和断言的字节码根进行链上验证和计算。
合约和断言的字节码根是二进制默克尔树 的默克尔根,每个叶子是 16KiB 的指令。该库将计算任何合约或断言的字节码根/地址,从而允许验证部署的合约并在链上生成断言地址。
有关字节码库的实现详细信息,请参阅Sway Libs 文档 。
要使用字节码库,必须将 Sway Libs 添加到Forc.toml
文件中,然后将其导入到您的 Sway 项目中。要将 Sway Libs 添加为项目的依赖项,请参阅入门 。
要将字节码库导入到您的 Sway 智能合约中,请将以下内容添加到您的 Sway 文件中:
use sway_libs::bytecode::*;
一旦导入,使用字节码库就像调用所需的函数一样简单。以下是您可以使用的函数定义列表。
compute_bytecode_root()
compute_bytecode_root_with_configurables()
compute_predicate_address()
compute_predicate_address_with_configurables()
predicate_address_from_root()
swap_configurables()
verify_contract_bytecode()
verify_contract_bytecode_with_configurables()
verify_predicate_address()
verify_predicate_address_with_configurables()
请注意,如果您从 SDK 传递字节码并包含可配置的值,则提供的Vec<u8>
字节码必须被复制以使其可变。以下内容可添加以使您的字节码可变:
fn make_mutable(not_mutable_bytecode: Vec<u8>) {
// Copy the bytecode to a newly allocated memory to avoid memory ownership error.
let mut bytecode_slice = raw_slice::from_parts::<u8>(
alloc_bytes(not_mutable_bytecode.len()),
not_mutable_bytecode
.len(),
);
not_mutable_bytecode
.ptr()
.copy_bytes_to(bytecode_slice.ptr(), not_mutable_bytecode.len());
let mut bytecode_vec = Vec::from(bytecode_slice);
// You may now use `bytecode_vec` in your computation and verification function calls
}
下面的示例适用于内部合约调用。如果您从 SDK 传递字节码,请遵循上述已知问题中列出的步骤,以避免内存所有权错误。
给定一些字节码,您可以通过调用swap_configurables()
函数交换合约和断言的可配置项。
fn swap(my_bytecode: Vec<u8>, my_configurables: Vec<(u64, Vec<u8>)>) {
let mut my_bytecode = my_bytecode;
let resulting_bytecode: Vec<u8> = swap_configurables(my_bytecode, my_configurables);
}
要计算合约的字节码根,可以调用compute_bytecode_root()
或compute_bytecode_root_with_configurables()
函数。
fn compute_bytecode(my_bytecode: Vec<u8>) {
let root: b256 = compute_bytecode_root(my_bytecode);
}
fn compute_bytecode_configurables(my_bytecode: Vec<u8>, my_configurables: Vec<(u64, Vec<u8>)>) {
let mut my_bytecode = my_bytecode;
let root: b256 = compute_bytecode_root_with_configurables(my_bytecode, my_configurables);
}
要验证合约的字节码根,可以调用verify_bytecode_root()
或verify_contract_bytecode_with_configurables()
函数。
fn verify_contract(my_contract: ContractId, my_bytecode: Vec<u8>) {
verify_contract_bytecode(my_contract, my_bytecode);
// By reaching this line the contract has been verified to match the bytecode provided.
}
fn verify_contract_configurables(
my_contract: ContractId,
my_bytecode: Vec<u8>,
my_configurables: Vec<(u64, Vec<u8>)>,
) {
let mut my_bytecode = my_bytecode;
verify_contract_bytecode_with_configurables(my_contract, my_bytecode, my_configurables);
// By reaching this line the contract has been verified to match the bytecode provided.
}
要计算断言的地址,可以调用compute_predicate_address()
或compute_predicate_address_with_configurables()
函数。
fn compute_predicate(my_bytecode: Vec<u8>) {
let address: Address = compute_predicate_address(my_bytecode);
}
fn compute_predicate_configurables(my_bytecode: Vec<u8>, my_configurables: Vec<(u64, Vec<u8>)>) {
let mut my_bytecode = my_bytecode;
let address: Address = compute_predicate_address_with_configurables(my_bytecode, my_configurables);
}
如果您有断言的根,可以通过调用predicate_address_from_root()
函数计算其相应的断言地址。
fn predicate_address(my_root: b256) {
let address: Address = predicate_address_from_root(my_root);
}
要验证断言的地址,可以调用verify_predicate_address()
或verify_predicate_address_with_configurables()
函数。
fn verify_predicate(my_predicate: Address, my_bytecode: Vec<u8>) {
verify_predicate_address(my_predicate, my_bytecode);
// By reaching this line the predicate bytecode matches the address provided.
}
fn verify_predicate_configurables(
my_predicate: Address,
my_bytecode: Vec<u8>,
my_configurables: Vec<(u64, Vec<u8>)>,
) {
let mut my_bytecode = my_bytecode;
verify_predicate_address_with_configurables(my_predicate, my_bytecode, my_configurables);
// By reaching this line the predicate bytecode matches the address provided.
}