Skip to content

Commit

Permalink
Merge branch '2.0' into remove-milestones-mentions
Browse files Browse the repository at this point in the history
  • Loading branch information
DaughterOfMars authored Mar 14, 2024
2 parents bcd8e1b + d2aea56 commit 4d927ea
Show file tree
Hide file tree
Showing 26 changed files with 122 additions and 172 deletions.
3 changes: 1 addition & 2 deletions bindings/core/src/method/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,9 @@ pub enum ClientMethod {
},
/// Return the information of committee members at the given epoch index. If epoch index is not provided, the
/// current committee members are returned.
#[serde(rename_all = "camelCase")]
GetCommittee {
/// The epoch index to query.
epoch_index: Option<EpochIndex>,
epoch: Option<EpochIndex>,
},
/// Get issuance
GetIssuance,
Expand Down
2 changes: 1 addition & 1 deletion bindings/core/src/method_handler/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ pub(crate) async fn call_client_method_internal(
Response::Validators(client.get_validators(page_size, cursor).await?)
}
ClientMethod::GetValidator { account_id } => Response::Validator(client.get_validator(&account_id).await?),
ClientMethod::GetCommittee { epoch_index } => Response::Committee(client.get_committee(epoch_index).await?),
ClientMethod::GetCommittee { epoch } => Response::Committee(client.get_committee(epoch).await?),
ClientMethod::GetIssuance => Response::Issuance(client.get_issuance().await?),
ClientMethod::PostBlockRaw { block_bytes } => Response::BlockId(
client
Expand Down
6 changes: 3 additions & 3 deletions bindings/nodejs/lib/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,13 @@ export class Client {
/**
* Returns the information of committee members at the given epoch index. If epoch index is not provided, the
* current committee members are returned.
* GET /api/core/v3/committee/?epochIndex
* GET /api/core/v3/committee/?epoch
*/
async getCommittee(epochIndex?: EpochIndex): Promise<CommitteeResponse> {
async getCommittee(epoch?: EpochIndex): Promise<CommitteeResponse> {
const response = await this.methodHandler.callMethod({
name: 'getCommittee',
data: {
epochIndex,
epoch,
},
});

Expand Down
14 changes: 8 additions & 6 deletions bindings/nodejs/lib/types/block/output/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { SlotIndex } from '../slot';
import { Type } from 'class-transformer';
import { Transform, Type } from 'class-transformer';
import { Address, AddressDiscriminator } from '../address';
import {
BlockIssuerKey,
Expand All @@ -11,7 +11,7 @@ import {
import { u256, u64 } from '../../utils/type-aliases';
import { EpochIndex } from '../../block/slot';
import { NativeToken } from '../../models/native-token';
import { HexEncodedString } from '../../utils/hex-encoding';
import { HexEncodedString, hexToBigInt } from '../../utils/hex-encoding';

/**
* Printable ASCII characters.
Expand Down Expand Up @@ -147,16 +147,18 @@ class NativeTokenFeature extends Feature {
/**
* Amount of native tokens of the given Token ID.
*/
@Transform((value) => hexToBigInt(value.value))
readonly amount: u256;

/**
* Creates a new `NativeTokenFeature`.
* @param nativeToken The native token stored with the feature.
* @param id The identifier of the native token.
* @param amount The native token amount.
*/
constructor(nativeToken: NativeToken) {
constructor(id: HexEncodedString, amount: u256) {
super(FeatureType.NativeToken);
this.id = nativeToken.id;
this.amount = nativeToken.amount;
this.id = id;
this.amount = amount;
}

/**
Expand Down
1 change: 1 addition & 0 deletions bindings/nodejs/lib/types/block/output/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class BasicOutput extends CommonOutput {

/**
* @param amount The amount of the output.
* @param mana The mana of the output.
* @param unlockConditions The unlock conditions for the output.
*/
constructor(amount: u64, mana: u64, unlockConditions: UnlockCondition[]) {
Expand Down
2 changes: 1 addition & 1 deletion bindings/nodejs/lib/types/client/bridge/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export interface __GetValidatorMethod__ {
export interface __GetCommitteeMethod__ {
name: 'getCommittee';
data: {
epochIndex?: EpochIndex;
epoch?: EpochIndex;
};
}

Expand Down
2 changes: 0 additions & 2 deletions bindings/nodejs/lib/types/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export type ClientErrorName =
| 'inputAddressNotFound'
| 'invalidAmount'
| 'invalidMnemonic'
| 'invalidTransactionLength'
| 'invalidSignedTransactionPayloadLength'
| 'json'
| 'missingParameter'
| 'node'
Expand Down
6 changes: 3 additions & 3 deletions bindings/python/iota_sdk/client/_node_core_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ def get_validator(self, account_id: HexStr) -> ValidatorResponse:
# Committee routes.

def get_committee(
self, epoch_index: Optional[EpochIndex] = None) -> CommitteeResponse:
self, epoch: Optional[EpochIndex] = None) -> CommitteeResponse:
"""Returns the information of committee members at the given epoch index. If epoch index is not provided, the
current committee members are returned.
GET /api/core/v3/committee/?epochIndex
GET /api/core/v3/committee/?epoch
"""
return CommitteeResponse.from_dict(self._call_method('getCommittee', {
'epochIndex': epoch_index
'epoch': epoch
}))

# Block routes.
Expand Down
2 changes: 0 additions & 2 deletions sdk/examples/wallet/offline_signing/2_sign_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let signed_transaction = SignedTransactionPayload::new(prepared_transaction_data.transaction.clone(), unlocks)?;

signed_transaction.validate_length()?;

let signed_transaction_data = SignedTransactionData {
payload: signed_transaction,
inputs_data: prepared_transaction_data.inputs_data,
Expand Down
58 changes: 1 addition & 57 deletions sdk/src/client/api/block_builder/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,15 @@

//! Transaction preparation and signing
use packable::PackableExt;

use crate::{
client::{
api::{PreparedTransactionData, SignedTransactionData},
ClientError,
},
client::api::{PreparedTransactionData, SignedTransactionData},
types::block::{
output::{Output, OutputId},
payload::signed_transaction::{SignedTransactionPayload, Transaction},
protocol::ProtocolParameters,
semantic::{SemanticValidationContext, TransactionFailureReason},
signature::Ed25519Signature,
Block, BlockId,
},
};

const MAX_TX_LENGTH_FOR_BLOCK_WITH_8_PARENTS: usize = Block::LENGTH_MAX - Block::LENGTH_MIN - (7 * BlockId::LENGTH);
// Length for unlocks with a single signature unlock (unlocks length + unlock type + signature type + public key +
// signature)
const SINGLE_UNLOCK_LENGTH: usize = 1 + 1 + Ed25519Signature::PUBLIC_KEY_LENGTH + Ed25519Signature::SIGNATURE_LENGTH;
// Type + reference index
const REFERENCE_ACCOUNT_NFT_UNLOCK_LENGTH: usize = 1 + 2;

impl PreparedTransactionData {
/// Verifies the semantic of a prepared transaction.
pub fn verify_semantic(&self, protocol_parameters: &ProtocolParameters) -> Result<(), TransactionFailureReason> {
Expand Down Expand Up @@ -68,44 +53,3 @@ impl SignedTransactionData {
context.validate()
}
}

impl SignedTransactionPayload {
/// Verifies that the signed transaction payload doesn't exceed the block size limit with 8 parents.
pub fn validate_length(&self) -> Result<(), ClientError> {
let signed_transaction_payload_bytes = self.pack_to_vec();
if signed_transaction_payload_bytes.len() > MAX_TX_LENGTH_FOR_BLOCK_WITH_8_PARENTS {
return Err(ClientError::InvalidSignedTransactionPayloadLength {
length: signed_transaction_payload_bytes.len(),
max_length: MAX_TX_LENGTH_FOR_BLOCK_WITH_8_PARENTS,
});
}
Ok(())
}
}

impl Transaction {
/// Verifies that the transaction doesn't exceed the block size limit with 8 parents.
/// Assuming one signature unlock and otherwise reference/account/nft unlocks.
/// `validate_transaction_payload_length()` should later be used to check the length again with the correct
/// unlocks.
pub fn validate_length(&self) -> Result<(), ClientError> {
let transaction_bytes = self.pack_to_vec();

// Assuming there is only 1 signature unlock and the rest is reference/account/nft unlocks
let reference_account_nft_unlocks_amount = self.inputs().len() - 1;

// Max tx payload length - length for one signature unlock (there might be more unlocks, we check with them
// later again, when we built the transaction payload)
let max_length = MAX_TX_LENGTH_FOR_BLOCK_WITH_8_PARENTS
- SINGLE_UNLOCK_LENGTH
- (reference_account_nft_unlocks_amount * REFERENCE_ACCOUNT_NFT_UNLOCK_LENGTH);

if transaction_bytes.len() > max_length {
return Err(ClientError::InvalidTransactionLength {
length: transaction_bytes.len(),
max_length,
});
}
Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ pub enum TransactionBuilderError {
required: u64,
},
/// Insufficient mana provided.
#[error("insufficient mana: found {found}, required {required}")]
#[error(
"insufficient mana: found {found}, required {required}, slots remaining until enough mana {slots_remaining}"
)]
InsufficientMana {
/// The amount found.
found: u64,
Expand Down
6 changes: 1 addition & 5 deletions sdk/src/client/api/block_builder/transaction_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,7 @@ impl Client {
transaction_builder = transaction_builder.disable_additional_input_selection();
}

let prepared_transaction_data = transaction_builder.finish()?;

prepared_transaction_data.transaction.validate_length()?;

Ok(prepared_transaction_data)
Ok(transaction_builder.finish()?)
}
}

Expand Down
20 changes: 13 additions & 7 deletions sdk/src/client/api/wait_for_tx_acceptance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ impl Client {
.unwrap_or(DEFAULT_WAIT_FOR_TX_ACCEPTANCE_INTERVAL);

for _ in 0..max_attempts.unwrap_or(DEFAULT_WAIT_FOR_TX_ACCEPTANCE_MAX_ATTEMPTS) {
let transaction_metadata = self.get_transaction_metadata(transaction_id).await?;

match transaction_metadata.transaction_state {
TransactionState::Accepted | TransactionState::Committed | TransactionState::Finalized => {
return Ok(());
match self.get_transaction_metadata(transaction_id).await {
Ok(transaction_metadata) => {
match transaction_metadata.transaction_state {
TransactionState::Accepted | TransactionState::Committed | TransactionState::Finalized => {
return Ok(());
}
TransactionState::Failed => {
return Err(ClientError::TransactionAcceptance(transaction_id.to_string()));
}
TransactionState::Pending => {} // Just need to wait longer
};
}
TransactionState::Failed => return Err(ClientError::TransactionAcceptance(transaction_id.to_string())),
TransactionState::Pending => {} // Just need to wait longer
Err(ClientError::Node(crate::client::node_api::error::Error::NotFound(_))) => {}
Err(e) => return Err(e),
};

#[cfg(target_family = "wasm")]
Expand Down
16 changes: 0 additions & 16 deletions sdk/src/client/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,6 @@ pub enum ClientError {
/// Invalid mnemonic error
#[error("invalid mnemonic {0}")]
InvalidMnemonic(String),
/// The transaction is too large
#[error("the transaction is too large. Its length is {length}, max length is {max_length}")]
InvalidTransactionLength {
/// The found length.
length: usize,
/// The max supported length.
max_length: usize,
},
/// The signed transaction payload is too large
#[error("the signed transaction payload is too large. Its length is {length}, max length is {max_length}")]
InvalidSignedTransactionPayloadLength {
/// The found length.
length: usize,
/// The max length.
max_length: usize,
},
/// JSON error
#[error("{0}")]
Json(#[from] serde_json::Error),
Expand Down
8 changes: 4 additions & 4 deletions sdk/src/client/node_api/core/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
pub(crate) static INFO_PATH: &str = "api/core/v3/info";

/// Contains the info and the url from the node (useful when multiple nodes are used)
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NodeInfoResponse {
/// The returned info
Expand Down Expand Up @@ -167,13 +167,13 @@ impl Client {

/// Returns the information of committee members at the given epoch index. If epoch index is not provided, the
/// current committee members are returned.
/// GET /api/core/v3/committee/?epochIndex
/// GET /api/core/v3/committee/?epoch
pub async fn get_committee(
&self,
epoch_index: impl Into<Option<EpochIndex>> + Send,
epoch: impl Into<Option<EpochIndex>> + Send,
) -> Result<CommitteeResponse, ClientError> {
const PATH: &str = "api/core/v3/committee";
let query = query_tuples_to_query_string([epoch_index.into().map(|i| ("epochIndex", i.to_string()))]);
let query = query_tuples_to_query_string([epoch.into().map(|i| ("epoch", i.to_string()))]);

self.get_request(PATH, query.as_deref(), false).await
}
Expand Down
2 changes: 0 additions & 2 deletions sdk/src/client/secret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,6 @@ where
} = prepared_transaction_data;
let tx_payload = SignedTransactionPayload::new(transaction, unlocks)?;

tx_payload.validate_length()?;

let data = SignedTransactionData {
payload: tx_payload,
inputs_data,
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/types/api/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct RoutesResponse {

/// Response of GET /api/core/v3/info.
/// General information about the node.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InfoResponse {
pub name: String,
Expand Down
4 changes: 4 additions & 0 deletions sdk/src/types/block/payload/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ pub enum PayloadError {
InputCount(<InputCount as TryFrom<usize>>::Error),
#[display(fmt = "invalid output count: {_0}")]
OutputCount(<OutputCount as TryFrom<usize>>::Error),
#[display(fmt = "the signed transaction payload is too large. Its length is {length}, max length is {max_length}")]
SignedTransactionPayloadLength { length: usize, max_length: usize },
#[display(fmt = "invalid transaction amount sum: {_0}")]
TransactionAmountSum(u128),
#[display(fmt = "the transaction is too large. Its length is {length}, max length is {max_length}")]
TransactionLength { length: usize, max_length: usize },
#[display(fmt = "duplicate output chain: {_0}")]
DuplicateOutputChain(ChainId),
#[display(fmt = "duplicate UTXO {_0} in inputs")]
Expand Down
18 changes: 18 additions & 0 deletions sdk/src/types/block/payload/signed_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod transaction_id;

use packable::{Packable, PackableExt};

use self::transaction::MAX_TX_LENGTH_FOR_BLOCK_WITH_SINGLE_PARENT;
pub(crate) use self::transaction::{InputCount, OutputCount};
pub use self::{
transaction::{Transaction, TransactionBuilder, TransactionCapabilities, TransactionCapabilityFlag},
Expand Down Expand Up @@ -69,9 +70,26 @@ fn verify_signed_transaction_payload(payload: &SignedTransactionPayload) -> Resu
});
}

payload.validate_length()?;

Ok(())
}

impl SignedTransactionPayload {
/// Verifies that the transaction doesn't exceed the block size limit with 1 parent.
fn validate_length(&self) -> Result<(), PayloadError> {
let signed_transaction_payload_bytes = self.pack_to_vec();
if signed_transaction_payload_bytes.len() > MAX_TX_LENGTH_FOR_BLOCK_WITH_SINGLE_PARENT {
return Err(PayloadError::SignedTransactionPayloadLength {
length: signed_transaction_payload_bytes.len(),
max_length: MAX_TX_LENGTH_FOR_BLOCK_WITH_SINGLE_PARENT,
});
}

Ok(())
}
}

#[cfg(feature = "serde")]
pub mod dto {
use alloc::vec::Vec;
Expand Down
Loading

0 comments on commit 4d927ea

Please sign in to comment.