Skip to content

Commit

Permalink
Bytecode Root Solver Library (#211)
Browse files Browse the repository at this point in the history
## Type of change

<!--Delete points that do not apply-->

- New feature

## Changes

The following changes have been made:

- Added `compute_bytecode_root()` function
- Added `compute_bytecode_root_with_configurables()` function
- Added `compute_predicate_address()` function
- Added `compute_predicate_address_with_configurables()` function
- Added `predicate_address_from_root()` function
- Added `swap_configurables()` function
- Added `verify_contract_bytecode()` function
- Added `verify_contract_bytecode_with_configurables()` function
- Added `verify_predicate_address()` function
- Added `verify_predicate_address_with_configurables()` function

## Notes

- While computationally expensive, these functions will allow for
certain use cases such as contract and predicate factories
  • Loading branch information
bitzoic authored Feb 14, 2024
1 parent afedd58 commit dcbbec0
Show file tree
Hide file tree
Showing 35 changed files with 2,369 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ These libraries contain helper functions and other tools valuable to blockchain

#### Cryptography

- [Bytecode](./libs/bytecode/) is used for on-chain verification and computation of bytecode roots for contracts and predicates.
- [Merkle Proof](./libs/merkle_proof/) is used to verify Binary Merkle Trees computed off-chain.

#### Math
Expand Down
1 change: 1 addition & 0 deletions libs/Forc.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"admin",
"bytecode",
"fixed_point",
"merkle_proof",
"native_asset",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added libs/bytecode/.docs/bytecode-logo-light-theme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions libs/bytecode/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "lib.sw"
license = "Apache-2.0"
name = "bytecode"
103 changes: 103 additions & 0 deletions libs/bytecode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset=".docs/bytecode-logo-dark-theme.png">
<img alt="Bytecode logo" width="400px" src=".docs/bytecode-logo-light-theme.png">
</picture>
</p>

# Overview

The Bytecode Library allows for on-chain verification and computation of bytecode roots for contracts and predicates.

A bytecode root for a contract and predicate is the Merkle root of the [binary Merkle tree](https://github.com/FuelLabs/fuel-specs/blob/master/src/protocol/cryptographic-primitives.md#binary-merkle-tree) with each leaf being 16KiB of instructions. This library will compute any contract's or predicate's bytecode root/address allowing for the verification of deployed contracts and generation of predicate addresses on-chain.

More information can be found in the [specification](./SPECIFICATION.md).

# Using the Library

## Using the Bytecode Library In Sway

In order to use the Bytecode Library it must be added to the `Forc.toml` file and then imported into your Sway project. To add Sway-libs as a dependency to the `Forc.toml` file in your project please see the [README.md](../../README.md).

You may import the Bytecode Library's functionalities like so:

```sway
use bytecode::*;
```

Once imported, using the Bytecode Library is as simple as calling the desired function. Here is a list of function definitions that you may use. For more information please see the [specification](./SPECIFICATION.md).

- `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()`

## Basic Functionality

Please note that if you are passing the bytecode from the SDK and are including configurable values, the `Vec<u8>` bytecode provided must be copied to be mutable. The examples below are intended for internal contract calls.

## Contracts

To compute a contract's bytecode root you may call the `compute_bytecode_root()` or `compute_bytecode_root_with_configurables()` functions.

```sway
fn foo(my_bytecode: Vec<u8>) {
let root: b256 = compute_bytecode_root(my_bytecode);
}
fn bar(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);
}
```

To verify a contract's bytecode root you may call `compute_bytecode_root()` or `verify_contract_bytecode_with_configurables()` functions.

```sway
fn foo(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 bar(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.
}
```

## Predicates

To compute a predicates's address you may call the `compute_predicate_address()` or `compute_predicate_address_with_configurables()` functions.

```sway
fn foo(my_bytecode: Vec<u8>) {
let address: Address = compute_predicate_address(my_bytecode);
}
fn bar(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);
}
```

To verify a predicates's address you may call `verify_predicate_address()` or `verify_predicate_address_with_configurables()` functions.

```sway
fn foo(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 bar(my_predicate: Address, my_bytecode: Vec<u8>, my_configurables: Vec<(u64, Vec<u8>)>) {
let mut my_bytecode = my_bytecode;
verify_predicate_bytecode_with_configurables(my_predicate, my_bytecode, my_configurables);
// By reaching this line the predicate bytecode matches the address provided.
}
```
51 changes: 51 additions & 0 deletions libs/bytecode/SPECIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Overview

This document provides an overview of the Bytecode Library.

It outlines the use cases, i.e. specification, and describes how to implement the library.

## Use Cases

The Bytecode Library can be used anytime some contract or predicate bytecode must be verified, manipulated, or the bytecode root must be computed.

## Public Functions

### `compute_bytecode_root()`

Takes the bytecode of a contract or predicate and computes the bytecode root.

### `compute_bytecode_root_with_configurables()`

Takes the bytecode of a contract or predicate and configurables and computes the bytecode root.

### `compute_predicate_address()`

Takes the bytecode of a predicate and computes the address of a predicate.

### `compute_predicate_address_with_configurables()`

Takes the bytecode of a predicate and configurables and computes the address of a predicate.

### `predicate_address_from_root()`

Takes the bytecode root of predicate generates the address of a predicate.

### `swap_configurables()`

Swaps out configurable values in a contract or predicate's bytecode.

### `verify_contract_bytecode()`

Asserts that a contract's bytecode and the given bytecode match.

### `verify_contract_bytecode_with_configurables()`

Asserts that a contract's bytecode and the given bytecode and configurable values match.

### `verify_predicate_address()`

Asserts that a predicates's address from some bytecode and the given address match.

### `verify_predicate_address_with_configurables()`

Asserts that a predicates's address from some bytecode and configurables and the given address match.
Loading

0 comments on commit dcbbec0

Please sign in to comment.