Skip to content

Commit

Permalink
feat: vector input support (#597)
Browse files Browse the repository at this point in the history
feat: vectors are supported as inputs

Besides that, encoding tokens will no longer provide you with raw bytes. To get those you need to provide the loading address for the bytes as well.
  • Loading branch information
segfault-magnet committed Oct 3, 2022
1 parent 8ce1080 commit 450e9ae
Show file tree
Hide file tree
Showing 25 changed files with 1,168 additions and 297 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env:
RUSTFLAGS: "-D warnings"
FUEL_CORE_VERSION: 0.10.1
RUST_VERSION: 1.61.0
FORC_VERSION: 0.24.4
FORC_VERSION: 0.24.5

jobs:
setup-test-projects:
Expand Down
3 changes: 2 additions & 1 deletion docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
- [Structs and enums](./types/custom_types.md)
- [String](./types/string.md)
- [Bits256](./types/bits256.md)
- [Vectors](./types/vectors.md)
- [API](./getting-started/api.md)
- [Debugging](./debugging/debugging.md)
- [Debugging abigen errors](./debugging/abigen.md)
Expand All @@ -55,7 +56,7 @@
- [Running scripts](./testing/scripts.md)
- [Tweaking the blockchain](./testing/chains.md)
- [Cookbook](./cookbook/cookbook.md)
- [Custom consesuns parameters](./cookbook/custom-chain.md)
- [Custom consensus parameters](./cookbook/custom-chain.md)
- [Deposit and Withdraw](./cookbook/deposit-and-withdraw.md)
- [Transfer all assets](./cookbook/transfer-all-assets.md)
- [Command Line Interfaces](./cli/index.md)
Expand Down
1 change: 0 additions & 1 deletion docs/src/types/custom_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ For instance, your Sway contract could look like this:
```Rust
contract;

use std::assert::assert;
use std::hash::sha256;

struct SimpleGeneric<T> {
Expand Down
15 changes: 15 additions & 0 deletions docs/src/types/vectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Vectors

## Passing in vectors

You can pass a Rust `std::vec::Vec` into your contract method transparently. The following code calls a Sway function which accepts and then returns a `Vec<SomeStruct<u32>>`.

```rust,ignore
{{#include ../../../packages/fuels/tests/harness.rs:passing_in_vec}}
```

You can use a vector just like you would use any other type -- e.g. a `[Vec<u32>; 2]` or a `SomeStruct<Vec<Bits256>>` etc.

## Returning vectors

This is currently not supported. If you try returning a type that is or contains a vector you will get a compile time error.
12 changes: 7 additions & 5 deletions packages/fuels-contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use fuel_gql_client::{
};

use fuels_core::abi_decoder::ABIDecoder;
use fuels_core::abi_encoder::ABIEncoder;
use fuels_core::abi_encoder::{ABIEncoder, UnresolvedBytes};
use fuels_core::parameters::StorageConfiguration;
use fuels_core::tx::{Bytes32, ContractId};
use fuels_core::{
Expand Down Expand Up @@ -131,18 +131,18 @@ impl Contract {
signature: Selector,
args: &[Token],
) -> Result<ContractCallHandler<D>, Error> {
let encoded_args = ABIEncoder::encode(args).unwrap();
let encoded_selector = signature;

let tx_parameters = TxParameters::default();
let call_parameters = CallParameters::default();

let compute_custom_input_offset = Contract::should_compute_custom_input_offset(args);

let unresolved_bytes = ABIEncoder::encode(args)?;
let contract_call = ContractCall {
contract_id,
encoded_selector,
encoded_args,
encoded_args: unresolved_bytes,
call_parameters,
compute_custom_input_offset,
variable_outputs: None,
Expand Down Expand Up @@ -175,6 +175,7 @@ impl Contract {
| Token::Tuple(_)
| Token::Array(_)
| Token::Byte(_)
| Token::Vector(_)
)
})
}
Expand Down Expand Up @@ -357,7 +358,7 @@ impl Contract {
/// Contains all data relevant to a single contract call
pub struct ContractCall {
pub contract_id: Bech32ContractId,
pub encoded_args: Vec<u8>,
pub encoded_args: UnresolvedBytes,
pub encoded_selector: Selector,
pub call_parameters: CallParameters,
pub compute_custom_input_offset: bool,
Expand All @@ -378,7 +379,7 @@ impl ContractCall {

let (encoded_value, index) = match param_type.get_return_location() {
ReturnLocation::ReturnData => {
match receipts.iter().find(|&receipt| receipt.data().is_some()) {
match receipts.iter().find(|&receipt| matches!(receipt, Receipt::ReturnData { data, .. } if !data.is_empty())) {
Some(r) => {
let index = receipts.iter().position(|elt| elt == r).unwrap();
(r.data().unwrap().to_vec(), Some(index))
Expand Down Expand Up @@ -484,6 +485,7 @@ where
Some(ref mut outputs) => outputs.extend(new_message_outputs),
None => self.contract_call.message_outputs = Some(new_message_outputs),
}

self
}

Expand Down
31 changes: 19 additions & 12 deletions packages/fuels-contract/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,19 @@ impl Script {
// one argument, we need to calculate the `call_data_offset`,
// which points to where the data for the custom types start in the
// transaction. If it doesn't take any custom inputs, this isn't necessary.
if call.compute_custom_input_offset {
let encoded_args_start_offset = if call.compute_custom_input_offset {
// Custom inputs are stored after the previously added parameters,
// including custom_input_offset
let custom_input_offset =
segment_offset + AssetId::LEN + 2 * WORD_SIZE + ContractId::LEN + 2 * WORD_SIZE;
let custom_input_offset = custom_input_offset as Word;

script_data.extend(&custom_input_offset.to_be_bytes());
}
script_data.extend(&(custom_input_offset as Word).to_be_bytes());
custom_input_offset
} else {
segment_offset
};

script_data.extend(call.encoded_args.clone());
let bytes = call.encoded_args.resolve(encoded_args_start_offset as u64);
script_data.extend(bytes);

// the data segment that holds the parameters for the next call
// begins at the original offset + the data we added so far
Expand Down Expand Up @@ -397,7 +399,9 @@ impl Script {
mod test {
use super::*;
use fuel_gql_client::client::schema::coin::CoinStatus;
use fuels_core::abi_encoder::ABIEncoder;
use fuels_core::parameters::CallParameters;
use fuels_core::Token;
use fuels_types::bech32::Bech32ContractId;
use fuels_types::param_types::ParamType;
use rand::Rng;
Expand All @@ -423,8 +427,11 @@ mod test {

let selectors = vec![[7u8; 8], [8u8; 8], [9u8; 8]];

// Call 2 has a multiple inputs, compute_custom_input_offset will be true
let args = vec![[10u8; 8].to_vec(), [11u8; 16].to_vec(), [12u8; 8].to_vec()];
// Call 2 has multiple inputs, compute_custom_input_offset will be true

let args = [Token::U8(1), Token::U16(2), Token::U8(3)]
.map(|token| ABIEncoder::encode(&[token]).unwrap())
.to_vec();

let calls: Vec<ContractCall> = (0..NUM_CALLS)
.map(|i| ContractCall {
Expand Down Expand Up @@ -477,11 +484,11 @@ mod test {
// Calls 1 and 3 have their input arguments after the selector
let call_1_arg_offset = param_offsets[0].call_data_offset + ContractId::LEN + SELECTOR_LEN;
let call_1_arg = script_data[call_1_arg_offset..call_1_arg_offset + WORD_SIZE].to_vec();
assert_eq!(call_1_arg, args[0].to_vec());
assert_eq!(call_1_arg, args[0].resolve(0));

let call_3_arg_offset = param_offsets[2].call_data_offset + ContractId::LEN + SELECTOR_LEN;
let call_3_arg = script_data[call_3_arg_offset..call_3_arg_offset + WORD_SIZE].to_vec();
assert_eq!(call_3_arg, args[2]);
assert_eq!(call_3_arg, args[2].resolve(0));

// Call 2 has custom inputs and custom_input_offset
let call_2_arg_offset = param_offsets[1].call_data_offset + ContractId::LEN + SELECTOR_LEN;
Expand All @@ -495,8 +502,8 @@ mod test {
let custom_input_offset =
param_offsets[1].call_data_offset + ContractId::LEN + SELECTOR_LEN + WORD_SIZE;
let custom_input =
script_data[custom_input_offset..custom_input_offset + 2 * WORD_SIZE].to_vec();
assert_eq!(custom_input, args[1]);
script_data[custom_input_offset..custom_input_offset + WORD_SIZE].to_vec();
assert_eq!(custom_input, args[1].resolve(0));
}

#[test]
Expand Down
Loading

0 comments on commit 450e9ae

Please sign in to comment.