Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add support for Transaction::Upload, Transaction::Upgrade, and Transaction::Blob #6500

Merged
merged 18 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions sway-lib-std/src/inputs.sw
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ use ::tx::{
tx_type,
};
use core::ops::Eq;

const GTF_INPUT_TYPE = 0x200;
use ::revert::revert;

// GTF Opcode const selectors
//
pub const GTF_INPUT_TYPE = 0x200;
// pub const GTF_INPUT_COIN_TX_ID = 0x201;
// pub const GTF_INPUT_COIN_OUTPUT_INDEX = 0x202;
pub const GTF_INPUT_COIN_OWNER = 0x203;
Expand All @@ -33,7 +32,7 @@ pub const GTF_INPUT_COIN_PREDICATE_LENGTH = 0x209;
pub const GTF_INPUT_COIN_PREDICATE_DATA_LENGTH = 0x20A;
pub const GTF_INPUT_COIN_PREDICATE = 0x20B;
pub const GTF_INPUT_COIN_PREDICATE_DATA = 0x20C;

// pub const GTF_INPUT_COIN_PREDICATE_GAS_USED = 0x20D;
// pub const GTF_INPUT_CONTRACT_CONTRACT_ID = 0x225;
pub const GTF_INPUT_MESSAGE_SENDER = 0x240;
pub const GTF_INPUT_MESSAGE_RECIPIENT = 0x241;
Expand All @@ -46,6 +45,7 @@ pub const GTF_INPUT_MESSAGE_PREDICATE_DATA_LENGTH = 0x247;
pub const GTF_INPUT_MESSAGE_DATA = 0x248;
pub const GTF_INPUT_MESSAGE_PREDICATE = 0x249;
pub const GTF_INPUT_MESSAGE_PREDICATE_DATA = 0x24A;
// pub const GTF_INPUT_MESSAGE_PREDICATE_GAS_USED = 0x24B;

/// The input type for a transaction.
pub enum Input {
Expand Down Expand Up @@ -127,6 +127,7 @@ pub fn input_count() -> u16 {
match tx_type() {
Transaction::Script => __gtf::<u16>(0, GTF_SCRIPT_INPUTS_COUNT),
Transaction::Create => __gtf::<u16>(0, GTF_CREATE_INPUTS_COUNT),
_ => revert(0),
}
}

Expand Down Expand Up @@ -158,6 +159,7 @@ fn input_pointer(index: u64) -> Option<raw_ptr> {
match tx_type() {
Transaction::Script => Some(__gtf::<raw_ptr>(index, GTF_SCRIPT_INPUT_AT_INDEX)),
Transaction::Create => Some(__gtf::<raw_ptr>(index, GTF_CREATE_INPUT_AT_INDEX)),
_ => None,
}
}

Expand Down
2 changes: 2 additions & 0 deletions sway-lib-std/src/outputs.sw
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fn output_pointer(index: u64) -> Option<raw_ptr> {
match tx_type() {
Transaction::Script => Some(__gtf::<raw_ptr>(index, GTF_SCRIPT_OUTPUT_AT_INDEX)),
Transaction::Create => Some(__gtf::<raw_ptr>(index, GTF_CREATE_OUTPUT_AT_INDEX)),
_ => None,
}
}

Expand Down Expand Up @@ -139,6 +140,7 @@ pub fn output_count() -> u16 {
match tx_type() {
Transaction::Script => __gtf::<u16>(0, GTF_SCRIPT_OUTPUTS_COUNT),
Transaction::Create => __gtf::<u16>(0, GTF_CREATE_OUTPUTS_COUNT),
_ => revert(0),
}
}

Expand Down
49 changes: 46 additions & 3 deletions sway-lib-std/src/tx.sw
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub const GTF_SCRIPT_SCRIPT_DATA = 0x00A;
pub const GTF_SCRIPT_INPUT_AT_INDEX = 0x00B;
pub const GTF_SCRIPT_OUTPUT_AT_INDEX = 0x00C;
pub const GTF_SCRIPT_WITNESS_AT_INDEX = 0x00D;

pub const GTF_TX_LENGTH = 0x00E;

// pub const GTF_CREATE_BYTECODE_WITNESS_INDEX = 0x101;
Expand Down Expand Up @@ -46,10 +47,35 @@ pub enum Transaction {
Script: (),
/// A contract deployment transaction.
Create: (),
/// The transaction is created by the block producer and is not signed.
///
/// # Additional Information
///
/// NOTE: This should never be valid in execution but it provided for congruency to the FuelVM specs.
Mint: (),
/// The Upgrade transaction allows upgrading either consensus parameters or state transition function used by the network to produce future blocks.
Upgrade: (),
///The Upload transaction allows the huge bytecode to be divided into subsections and uploaded slowly to the chain.
Upload: (),
/// The Blob inserts a simple binary blob in the chain. It's raw immutable data that can be cheaply loaded by the VM and used as instructions or just data.
Blob: (),
}

impl core::ops::Eq for Transaction {
fn eq(self, other: Self) -> bool {
match (self, other) {
(Transaction::Script, Transaction::Script) => true,
(Transaction::Create, Transaction::Create) => true,
(Transaction::Mint, Transaction::Mint) => true,
(Transaction::Upgrade, Transaction::Upgrade) => true,
(Transaction::Upload, Transaction::Upload) => true,
(Transaction::Blob, Transaction::Blob) => true,
_ => false,
}
}
}

/// Get the type of the current transaction.
/// Either `Transaction::Script` or `Transaction::Create`.
///
/// # Returns
///
Expand All @@ -73,13 +99,28 @@ pub enum Transaction {
/// Transaction::Create => {
/// log("Contract deployment transaction");
/// },
/// Transaction::Mint => {
/// log("This should never happen");
/// },
/// Transaction::Upgrade => {
/// log("Upgrade transaction");
/// },
/// Transaction::Upload => {
/// log("Upload transaction");
/// },
/// Transaction::Blob => {
/// log("Blob transaction");
/// },
/// }
/// }
/// ```
pub fn tx_type() -> Transaction {
match __gtf::<u8>(0, GTF_TYPE) {
0u8 => Transaction::Script,
1u8 => Transaction::Create,
3u8 => Transaction::Upgrade,
4u8 => Transaction::Upload,
5u8 => Transaction::Blob,
_ => revert(0),
}
}
Expand Down Expand Up @@ -233,7 +274,7 @@ pub fn tx_max_fee() -> Option<u64> {
pub fn tx_script_length() -> Option<u64> {
match tx_type() {
Transaction::Script => Some(__gtf::<u64>(0, GTF_SCRIPT_SCRIPT_LENGTH)),
Transaction::Create => None,
_ => None,
}
}

Expand All @@ -256,7 +297,7 @@ pub fn tx_script_length() -> Option<u64> {
pub fn tx_script_data_length() -> Option<u64> {
match tx_type() {
Transaction::Script => Some(__gtf::<u64>(0, GTF_SCRIPT_SCRIPT_DATA_LENGTH)),
Transaction::Create => None,
_ => None,
}
}

Expand All @@ -280,6 +321,7 @@ pub fn tx_witnesses_count() -> u64 {
match tx_type() {
Transaction::Script => __gtf::<u64>(0, GTF_SCRIPT_WITNESSES_COUNT),
Transaction::Create => __gtf::<u64>(0, GTF_CREATE_WITNESSES_COUNT),
_ => revert(0),
}
}

Expand Down Expand Up @@ -311,6 +353,7 @@ fn tx_witness_pointer(index: u64) -> Option<raw_ptr> {
match tx_type() {
Transaction::Script => Some(__gtf::<raw_ptr>(index, GTF_SCRIPT_WITNESS_AT_INDEX)),
Transaction::Create => Some(__gtf::<raw_ptr>(index, GTF_CREATE_WITNESS_AT_INDEX)),
_ => None,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use test_fuel_coin_abi::*;
#[cfg(experimental_new_encoding = false)]
const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c;
#[cfg(experimental_new_encoding = true)]
const FUEL_COIN_CONTRACT_ID = 0xf8c7b4d09f9964ab4c437ac7f5cbd6dbad7e1f218fce452c5807aac3c67afa6f;
const FUEL_COIN_CONTRACT_ID = 0x4b651789d4867c17419e95cefd50f49bdc78e8778118373b7aab6bcab2ca3d1e;

#[cfg(experimental_new_encoding = false)]
const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df;
Expand Down
1 change: 1 addition & 0 deletions test/src/in_language_tests/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"test_programs/revert_inline_tests",
"test_programs/storage_key_inline_tests",
"test_programs/string_inline_tests",
"test_programs/tx_inline_tests",
"test_programs/u128_inline_tests",
"test_programs/vec_inline_tests",
"test_programs/array_conversions_b256_inline_tests",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "tx_inline_tests"

[dependencies]
std = { path = "../../../../../sway-lib-std" }
129 changes: 129 additions & 0 deletions test/src/in_language_tests/test_programs/tx_inline_tests/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
library;

use std::tx::Transaction;

#[test]
fn tx_transaction_eq() {
let transaction_1 = Transaction::Script;
let transaction_2 = Transaction::Script;
let transaction_3 = Transaction::Create;
let transaction_4 = Transaction::Create;
let transaction_5 = Transaction::Mint;
let transaction_6 = Transaction::Mint;
let transaction_7 = Transaction::Upgrade;
let transaction_8 = Transaction::Upgrade;
let transaction_9 = Transaction::Upload;
let transaction_10 = Transaction::Upload;
let transaction_11 = Transaction::Blob;
let transaction_12 = Transaction::Blob;

assert(transaction_1 == transaction_1);
assert(transaction_1 == transaction_2);
assert(transaction_2 == transaction_2);

assert(transaction_3 == transaction_3);
assert(transaction_3 == transaction_4);
assert(transaction_4 == transaction_4);

assert(transaction_5 == transaction_5);
assert(transaction_5 == transaction_6);
assert(transaction_6 == transaction_6);

assert(transaction_7 == transaction_7);
assert(transaction_7 == transaction_8);
assert(transaction_8 == transaction_8);

assert(transaction_9 == transaction_9);
assert(transaction_9 == transaction_10);
assert(transaction_10 == transaction_10);

assert(transaction_11 == transaction_11);
assert(transaction_11 == transaction_12);
assert(transaction_12 == transaction_12);
}

#[test]
fn tx_transaction_ne() {
let transaction_1 = Transaction::Script;
let transaction_2 = Transaction::Script;
let transaction_3 = Transaction::Create;
let transaction_4 = Transaction::Create;
let transaction_5 = Transaction::Mint;
let transaction_6 = Transaction::Mint;
let transaction_7 = Transaction::Upgrade;
let transaction_8 = Transaction::Upgrade;
let transaction_9 = Transaction::Upload;
let transaction_10 = Transaction::Upload;
let transaction_11 = Transaction::Blob;
let transaction_12 = Transaction::Blob;

assert(transaction_1 != transaction_3);
assert(transaction_1 != transaction_4);
assert(transaction_1 != transaction_5);
assert(transaction_1 != transaction_6);
assert(transaction_1 != transaction_7);
assert(transaction_1 != transaction_8);
assert(transaction_1 != transaction_9);
assert(transaction_1 != transaction_10);
assert(transaction_1 != transaction_11);
assert(transaction_1 != transaction_12);

assert(transaction_2 != transaction_3);
assert(transaction_2 != transaction_4);
assert(transaction_2 != transaction_5);
assert(transaction_2 != transaction_6);
assert(transaction_2 != transaction_7);
assert(transaction_2 != transaction_8);
assert(transaction_2 != transaction_9);
assert(transaction_2 != transaction_10);
assert(transaction_2 != transaction_11);
assert(transaction_2 != transaction_12);

assert(transaction_3 != transaction_5);
assert(transaction_3 != transaction_6);
assert(transaction_3 != transaction_7);
assert(transaction_3 != transaction_8);
assert(transaction_3 != transaction_9);
assert(transaction_3 != transaction_10);
assert(transaction_3 != transaction_11);
assert(transaction_3 != transaction_12);

assert(transaction_4 != transaction_5);
assert(transaction_4 != transaction_6);
assert(transaction_4 != transaction_7);
assert(transaction_4 != transaction_8);
assert(transaction_4 != transaction_9);
assert(transaction_4 != transaction_10);
assert(transaction_4 != transaction_11);
assert(transaction_4 != transaction_12);

assert(transaction_5 != transaction_7);
assert(transaction_5 != transaction_8);
assert(transaction_5 != transaction_9);
assert(transaction_5 != transaction_10);
assert(transaction_5 != transaction_11);
assert(transaction_5 != transaction_12);

assert(transaction_6 != transaction_7);
assert(transaction_6 != transaction_8);
assert(transaction_6 != transaction_9);
assert(transaction_6 != transaction_10);
assert(transaction_6 != transaction_11);
assert(transaction_6 != transaction_12);

assert(transaction_7 != transaction_9);
assert(transaction_7 != transaction_10);
assert(transaction_7 != transaction_11);
assert(transaction_7 != transaction_12);

assert(transaction_8 != transaction_9);
assert(transaction_8 != transaction_10);
assert(transaction_8 != transaction_11);
assert(transaction_8 != transaction_12);

assert(transaction_9 != transaction_11);
assert(transaction_9 != transaction_12);

assert(transaction_10 != transaction_11);
assert(transaction_10 != transaction_12);
}
5 changes: 5 additions & 0 deletions test/src/sdk-harness/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ name = "tx_output_predicate"
source = "member"
dependencies = ["std"]

[[package]]
name = "tx_type_predicate"
source = "member"
dependencies = ["std"]

[[package]]
name = "type_aliases"
source = "member"
Expand Down
3 changes: 2 additions & 1 deletion test/src/sdk-harness/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ members = [
"test_artifacts/storage_vec/svec_u16",
"test_artifacts/storage_vec/svec_u64",
"test_artifacts/tx_contract",
"test_artifacts/tx_output_predicate",
"test_artifacts/tx_output_contract_creation_predicate",
"test_artifacts/tx_output_predicate",
"test_artifacts/tx_type_predicate",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "tx_type_predicate"

[dependencies]
std = { path = "../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
predicate;

use std::tx::{tx_type, Transaction};

fn main(expected_type: Transaction) -> bool {
tx_type() == expected_type
}
4 changes: 2 additions & 2 deletions test/src/sdk-harness/test_projects/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ async fn can_get_predicate_address() {

// Setup predicate.
let hex_predicate_address: &str =
"0x188fb1615bacd24d52b1339fcfeed1ecf555d0afde44a087eebf98381c64db1b";
"0x8896a8f961e31af598faa2c4041d4d2745b0a11c57f8bb8bae65cff290076a74";
let predicate_address =
Address::from_str(hex_predicate_address).expect("failed to create Address from string");
let predicate_bech32_address = Bech32Address::from(predicate_address);
Expand Down Expand Up @@ -322,7 +322,7 @@ async fn when_incorrect_predicate_address_passed() {
async fn can_get_predicate_address_in_message() {
// Setup predicate address.
let hex_predicate_address: &str =
"0x188fb1615bacd24d52b1339fcfeed1ecf555d0afde44a087eebf98381c64db1b";
"0x8896a8f961e31af598faa2c4041d4d2745b0a11c57f8bb8bae65cff290076a74";
let predicate_address =
Address::from_str(hex_predicate_address).expect("failed to create Address from string");
let predicate_bech32_address = Bech32Address::from(predicate_address);
Expand Down
Loading
Loading