Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Blob tx and instructions #780

Merged
merged 45 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
41d1d50
Add blob tx
Dentosal Jun 20, 2024
34a23f8
Add some tests
Dentosal Jun 20, 2024
3f233a3
Add opcodes for blob storage access
Dentosal Jun 21, 2024
f47cddd
Freeze stack on DLDC instead of copying it over the data
Dentosal Jun 24, 2024
296e307
Add internal context test cases
Dentosal Jun 24, 2024
66023ef
Merge branch 'master' into dento/blob-tx
Dentosal Jun 24, 2024
d62708e
Add changelog entry
Dentosal Jun 24, 2024
9f84f36
Remove bldc. Allow executable stack.
Dentosal Jun 24, 2024
c316e33
Merge RunResult helper type with AluResult
Dentosal Jun 24, 2024
04e97f1
Move blob tx data to witness like other txs do
Dentosal Jun 26, 2024
56c8f84
Fixes for fuel-core
Dentosal Jun 26, 2024
586ece5
Merge branch 'master' into dento/blob-tx
Dentosal Jun 26, 2024
cc55e94
Merge RunResult types after branch merge
Dentosal Jun 26, 2024
7c0a013
Fix no_std imports
Dentosal Jun 26, 2024
08041d8
Add blob id validation rule
Dentosal Jun 26, 2024
98bdbc8
Add base_asset_id to blob::CheckedMetadata
Dentosal Jun 26, 2024
75e3149
Use LDC with mode argument instead of having separate blob instructions
Dentosal Jul 2, 2024
2b39ae9
Restore BSIZ and BLDD instructions
Dentosal Jul 2, 2024
0e0e79c
Merge branch 'master' into dento/blob-tx
Dentosal Jul 2, 2024
862687e
Merge branch 'master' into dento/blob-tx
Dentosal Jul 11, 2024
578b6b6
fmt
Dentosal Jul 11, 2024
d42c469
Update doc comment (PR feedback)
Dentosal Jul 15, 2024
3570b60
Improve test case names (pr feedback)
Dentosal Jul 22, 2024
2220fb5
Apply PR review suggestions
Dentosal Jul 22, 2024
476f2f4
Fix the serialization for the blob
xgreenx Jul 23, 2024
509cb57
Merge remote-tracking branch 'origin/dento/blob-tx' into dento/blob-tx
xgreenx Jul 23, 2024
a977954
Fix the serialization for the blob
xgreenx Jul 23, 2024
443f12d
Make clippy happy
xgreenx Jul 23, 2024
3a9f032
Add offset and encoding tests
Dentosal Jul 23, 2024
c844fe4
Add as_blob(_mut) for tx
Dentosal Jul 23, 2024
519839f
fix clippy
Dentosal Jul 23, 2024
1daad91
Fix offset tests (were targeting wrong tx type)
Dentosal Jul 24, 2024
00fa94a
Update fuel-tx/src/transaction/types/blob.rs
Dentosal Jul 25, 2024
6fcafd4
Address PR feedback
Dentosal Jul 25, 2024
ac2776a
More PR comments
Dentosal Jul 25, 2024
d38fc65
Disallow blob reupload
Dentosal Jul 25, 2024
3410794
Make memory access determintistic across 32 and 64 bit platforms
Dentosal Jul 25, 2024
460c003
Remove tests that were dependent on executable stack
Dentosal Jul 25, 2024
c723f3d
Charge BLDD based on max(load_len, blob_size)
Dentosal Jul 25, 2024
4fe7322
Add blob_id field getter test
Dentosal Jul 25, 2024
ddd0eb3
clippy
Dentosal Jul 25, 2024
c9fd164
Merge branch 'master' into dento/blob-tx
Dentosal Jul 25, 2024
02df199
Fix wrong test name
Dentosal Jul 26, 2024
7ebac9e
Address PR feedback
Dentosal Jul 26, 2024
5f62959
Remove redundant coin validity check clause
Dentosal Jul 26, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

#### Breaking
- [#780](https://github.com/FuelLabs/fuel-vm/pull/780): Added `Blob` transaction, and `BSIZ` and `BLDD` instructions. Also allows `LDC` to load blobs.

## [Version 0.55.0]

### Added
Expand Down
9 changes: 7 additions & 2 deletions fuel-asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl_instructions! {
"Get current block proposer's address."
0x31 CB cb [dst: RegId]
"Load a contract's code as executable."
0x32 LDC ldc [contract_id_addr: RegId offset: RegId len: RegId]
0x32 LDC ldc [contract_id_addr: RegId offset: RegId len: RegId mode: Imm06]
"Log an event."
0x33 LOG log [a: RegId b: RegId c: RegId d: RegId]
"Log data."
Expand Down Expand Up @@ -340,6 +340,11 @@ impl_instructions! {

"Call external function"
0xb0 ECAL ecal [a: RegId b: RegId c: RegId d: RegId]

"Get blob size"
0xba BSIZ bsiz [dst: RegId blob_id_ptr: RegId]
"Load blob as data"
0xbb BLDD bldd [dst_ptr: RegId blob_id_ptr: RegId offset: RegId len: RegId]
}

impl Instruction {
Expand Down Expand Up @@ -988,7 +993,7 @@ fn check_predicate_allowed() {
let should_allow = match repr {
BAL | BHEI | BHSH | BURN | CALL | CB | CCP | CROO | CSIZ | LDC | LOG
| LOGD | MINT | RETD | RVRT | SMO | SCWQ | SRW | SRWQ | SWW | SWWQ
| TIME | TR | TRO | ECAL => false,
| TIME | TR | TRO | ECAL | BSIZ | BLDD => false,
_ => true,
};
assert_eq!(should_allow, repr.is_predicate_allowed());
Expand Down
6 changes: 6 additions & 0 deletions fuel-asm/src/panic_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ enum_from! {
BytecodeAlreadyUploaded = 0x34,
/// The part of the bytecode is not sequentially connected to the previous parts.
ThePartIsNotSequentiallyConnected = 0x35,
/// The requested blob is not found.
BlobNotFound = 0x36,
/// The blob was already
BlobIdAlreadyUploaded = 0x37,
/// Active gas costs do not define the cost for this instruction.
GasCostNotDefined = 0x38,
}
}

Expand Down
16 changes: 16 additions & 0 deletions fuel-tx/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use crate::{
Executable,
Script,
},
Blob,
BlobBody,
ConsensusParameters,
ContractParameters,
CreateMetadata,
Expand Down Expand Up @@ -210,6 +212,20 @@ impl TransactionBuilder<Upload> {
}
}

impl TransactionBuilder<Blob> {
pub fn blob(body: BlobBody) -> Self {
let tx = Blob {
body,
policies: Policies::new().with_max_fee(0),
inputs: Default::default(),
outputs: Default::default(),
witnesses: Default::default(),
metadata: None,
};
Self::with_tx(tx)
}
}

impl TransactionBuilder<Mint> {
pub fn mint(
block_height: BlockHeight,
Expand Down
5 changes: 5 additions & 0 deletions fuel-tx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub use fuel_asm::{
pub use fuel_types::{
Address,
AssetId,
BlobId,
Bytes32,
Bytes4,
Bytes64,
Expand Down Expand Up @@ -83,6 +84,10 @@ pub use transaction::{
output::Output,
output::OutputRepr,
policies,
Blob,
BlobBody,
BlobIdExt,
BlobMetadata,
Cacheable,
Chargeable,
ChargeableMetadata,
Expand Down
46 changes: 45 additions & 1 deletion fuel-tx/src/test_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ mod use_std {
};
use crate::{
field,
Blob,
BlobBody,
BlobIdExt,
Buildable,
ConsensusParameters,
Contract,
Expand All @@ -68,7 +71,10 @@ mod use_std {
Hasher,
SecretKey,
};
use fuel_types::canonical::Deserialize;
use fuel_types::{
canonical::Deserialize,
BlobId,
};
use rand::{
distributions::{
Distribution,
Expand Down Expand Up @@ -134,6 +140,7 @@ mod use_std {
Transaction::Mint(_) => (),
Transaction::Upgrade(_) => (),
Transaction::Upload(_) => (),
Transaction::Blob(_) => (),
})
.unwrap_or(());

Expand Down Expand Up @@ -443,6 +450,32 @@ mod use_std {
}
}

impl<R> TransactionFactory<R, Blob>
where
R: Rng + CryptoRng,
{
pub fn transaction(&mut self) -> Blob {
self.transaction_with_keys().0
}

pub fn transaction_with_keys(&mut self) -> (Blob, Vec<SecretKey>) {
let len = self.rng.gen_range(1..1024 * 1024);

let mut bytecode = alloc::vec![0u8; len];
self.rng.fill_bytes(bytecode.as_mut_slice());

let mut builder = TransactionBuilder::<Blob>::blob(BlobBody {
id: BlobId::compute(&bytecode),
witness_index: 0,
});
debug_assert_eq!(builder.witnesses().len(), 0);
builder.add_witness(bytecode.into());

let keys = self.fill_transaction(&mut builder);
(builder.finalize(), keys)
}
}

impl<R> TransactionFactory<R, Mint>
where
R: Rng + CryptoRng,
Expand Down Expand Up @@ -506,6 +539,17 @@ mod use_std {
}
}

impl<R> Iterator for TransactionFactory<R, Blob>
where
R: Rng + CryptoRng,
{
type Item = (Blob, Vec<SecretKey>);

fn next(&mut self) -> Option<(Blob, Vec<SecretKey>)> {
Some(self.transaction_with_keys())
}
}

impl<R> Iterator for TransactionFactory<R, Mint>
where
R: Rng + CryptoRng,
Expand Down
60 changes: 58 additions & 2 deletions fuel-tx/src/tests/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

use crate::{
field::{
BlobId as BlobIdField,
BytecodeWitnessIndex,
InputContract,
Inputs,
MintAmount,
Expand All @@ -20,6 +22,7 @@ use crate::{
},
input,
test_helper::TransactionFactory,
BlobIdExt,
Upgrade,
*,
};
Expand Down Expand Up @@ -68,6 +71,14 @@ struct TestedFields {
}

fn chargeable_transaction_parts<Tx>(tx: &Tx, bytes: &[u8], cases: &mut TestedFields)
where
Tx: Buildable,
{
inputs_assert(tx, bytes, cases);
outputs_assert(tx, bytes, cases);
}

fn inputs_assert<Tx: Inputs>(tx: &Tx, bytes: &[u8], cases: &mut TestedFields)
where
Tx: Buildable,
{
Expand Down Expand Up @@ -247,8 +258,6 @@ where
}
}
});

outputs_assert(tx, bytes, cases);
}

fn outputs_assert<Tx: Outputs>(tx: &Tx, bytes: &[u8], cases: &mut TestedFields) {
Expand Down Expand Up @@ -530,6 +539,53 @@ fn tx_offset_upload() {
assert!(cases.output_contract_created_id);
}

#[test]
fn tx_offset_blob() {
let mut cases = TestedFields::default();
let number_cases = 100;

// The seed will define how the transaction factory will generate a new transaction.
// Different seeds might implicate on how many of the cases we cover - since we
// assert coverage for all scenarios with the boolean variables above, we need to
// pick a seed that, with low number of cases, will cover everything.
TransactionFactory::<_, Blob>::from_seed(1295)
.take(number_cases)
.for_each(|(tx, _)| {
let bytes = tx.to_bytes();

let i = *tx.bytecode_witness_index();
Dentosal marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(
BlobId::compute(tx.witnesses()[i as usize].as_ref()),
*tx.blob_id()
);

chargeable_transaction_parts(&tx, &bytes, &mut cases);
Dentosal marked this conversation as resolved.
Show resolved Hide resolved
});

// Chargeable parts
assert!(cases.utxo_id);
assert!(cases.owner);
assert!(cases.asset_id);
assert!(cases.predicate_coin);
assert!(cases.predicate_message);
assert!(cases.predicate_data_coin);
assert!(cases.predicate_data_message);
assert!(cases.contract_balance_root);
assert!(cases.contract_state_root);
assert!(cases.contract_id);
assert!(cases.sender);
assert!(cases.recipient);
assert!(cases.message_data);
assert!(cases.message_predicate);
assert!(cases.message_predicate_data);
assert!(cases.output_to);
assert!(cases.output_asset_id);
assert!(cases.output_balance_root);
assert!(cases.output_contract_state_root);
assert!(cases.output_contract_created_state_root);
assert!(cases.output_contract_created_id);
}

#[test]
fn tx_offset_mint() {
let number_cases = 100;
Expand Down
1 change: 1 addition & 0 deletions fuel-tx/src/tests/valid_cases/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![allow(clippy::cast_possible_truncation)]
#![allow(non_snake_case)]

mod blob;
mod upgrade;
mod upload;

Expand Down
Loading
Loading