Skip to content

Commit

Permalink
Merge branch '2.0' into feat/api/validators
Browse files Browse the repository at this point in the history
  • Loading branch information
Brord van Wierst authored Aug 25, 2023
2 parents 5dc3b87 + 51087bf commit e86789a
Show file tree
Hide file tree
Showing 41 changed files with 780 additions and 285 deletions.
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 @@ -289,7 +289,7 @@ pub(crate) async fn call_client_method_internal(client: &Client, method: ClientM
let output = Output::try_from_dto_with_params(output, client.get_token_supply().await?)?;
let rent_structure = client.get_rent_structure().await?;

let minimum_storage_deposit = output.rent_cost(&rent_structure);
let minimum_storage_deposit = output.rent_cost(rent_structure);

Response::MinimumRequiredStorageDeposit(minimum_storage_deposit.to_string())
}
Expand Down
2 changes: 1 addition & 1 deletion bindings/core/src/method_handler/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result<Response
}
UtilsMethod::ComputeStorageDeposit { output, rent } => {
let out = Output::try_from_dto(output)?;
Response::MinimumRequiredStorageDeposit(out.rent_cost(&rent).to_string())
Response::MinimumRequiredStorageDeposit(out.rent_cost(rent).to_string())
}
UtilsMethod::VerifyMnemonic { mnemonic } => {
let mnemonic = Mnemonic::from(mnemonic);
Expand Down
16 changes: 16 additions & 0 deletions bindings/nodejs/lib/types/block/context_input/context-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,26 @@ class RewardContextInput extends ContextInput {
}
}

const ContextInputDiscriminator = {
property: 'type',
subTypes: [
{
value: CommitmentContextInput,
name: ContextInputType.COMMITMENT as any,
},
{
value: BlockIssuanceCreditContextInput,
name: ContextInputType.BLOCK_ISSUANCE_CREDIT as any,
},
{ value: RewardContextInput, name: ContextInputType.REWARD as any },
],
};

export {
ContextInputType,
ContextInput,
CommitmentContextInput,
RewardContextInput,
BlockIssuanceCreditContextInput,
ContextInputDiscriminator,
};
54 changes: 34 additions & 20 deletions bindings/nodejs/lib/types/block/payload/transaction/essence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

import { Type } from 'class-transformer';
import { PayloadDiscriminator } from '..';
import { HexEncodedString } from '../../../utils';
import { HexEncodedString, u64 } from '../../../utils';
import { ContextInput, ContextInputDiscriminator } from '../../context_input';
import { Input, InputDiscriminator } from '../../input';
import { ManaAllotment } from '../../mana-allotment';
import { Output, OutputDiscriminator } from '../../output';
import { SlotIndex } from '../../slot';
import { Payload } from '../payload';

/**
Expand All @@ -16,55 +19,66 @@ enum TransactionEssenceType {
}

abstract class TransactionEssence {
private type: TransactionEssenceType;
readonly type: TransactionEssenceType;

constructor(type: TransactionEssenceType) {
this.type = type;
}

/**
* The type of essence.
*/
getType(): TransactionEssenceType {
return this.type;
}
}

/**
* RegularTransactionEssence transaction essence.
*/
class RegularTransactionEssence extends TransactionEssence {
/// The unique value denoting whether the block was meant for mainnet, testnet, or a private network.
networkId: number;
inputsCommitment: HexEncodedString;
/**
* The unique value denoting whether the block was meant for mainnet, testnet, or a private network.
*/
networkId: u64;

creationSlot: SlotIndex;

@Type(() => Input, {
discriminator: ContextInputDiscriminator,
})
contextInputs: ContextInput[];

@Type(() => Input, {
discriminator: InputDiscriminator,
})
inputs: [Input];
inputs: Input[];

inputsCommitment: HexEncodedString;

@Type(() => Output, {
discriminator: OutputDiscriminator,
})
outputs: [Output];
outputs: Output[];

allotments: ManaAllotment[];

@Type(() => Payload, {
discriminator: PayloadDiscriminator,
})
payload: Payload | undefined;
payload?: Payload;

constructor(
networkId: number,
networkId: u64,
creationSlot: SlotIndex,
contextInputs: ContextInput[],
inputs: Input[],
inputsCommitment: HexEncodedString,
inputs: [Input],
outputs: [Output],
payload: Payload | undefined,
outputs: Output[],
allotments: ManaAllotment[],
payload?: Payload,
) {
super(TransactionEssenceType.Regular);
this.networkId = networkId;
this.inputsCommitment = inputsCommitment;
this.creationSlot = creationSlot;
this.contextInputs = contextInputs;
this.inputs = inputs;
this.inputsCommitment = inputsCommitment;
this.outputs = outputs;
this.allotments = allotments;
this.payload = payload;
}
}
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/client/api/block_builder/input_selection/remainder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl InputSelection {
let native_tokens_remainder = native_tokens_diff.is_some();

let mut remainder_builder =
BasicOutputBuilder::new_with_minimum_storage_deposit(*self.protocol_parameters.rent_structure())
BasicOutputBuilder::new_with_minimum_storage_deposit(self.protocol_parameters.rent_structure())
.add_unlock_condition(AddressUnlockCondition::new(Address::from(Ed25519Address::from(
[0; 32],
))));
Expand Down Expand Up @@ -144,7 +144,7 @@ impl InputSelection {
log::debug!("Created remainder output of {diff} for {remainder_address:?}");

remainder.verify_storage_deposit(
*self.protocol_parameters.rent_structure(),
self.protocol_parameters.rent_structure(),
self.protocol_parameters.token_supply(),
)?;

Expand Down
11 changes: 5 additions & 6 deletions sdk/src/client/api/high_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,21 +114,20 @@ impl Client {
Ok(selected_inputs)
}

/// Returns the local time checked with the timestamp of the latest milestone, if the difference is larger than 5
/// Returns the local time checked with the tangle timestamp. If the difference is larger than 5
/// minutes an error is returned to prevent locking outputs by accident for a wrong time.
pub async fn get_time_checked(&self) -> Result<u32> {
let current_time = unix_timestamp_now().as_secs() as u32;

let network_info = self.get_network_info().await?;

if let Some(latest_ms_timestamp) = network_info.latest_milestone_timestamp {
if let Some(tangle_time) = network_info.tangle_time {
let tangle_time = tangle_time as u32;
// Check the local time is in the range of +-5 minutes of the node to prevent locking funds by accident
if !(latest_ms_timestamp - FIVE_MINUTES_IN_SECONDS..latest_ms_timestamp + FIVE_MINUTES_IN_SECONDS)
.contains(&current_time)
{
if !(tangle_time - FIVE_MINUTES_IN_SECONDS..tangle_time + FIVE_MINUTES_IN_SECONDS).contains(&current_time) {
return Err(Error::TimeNotSynced {
current_time,
milestone_timestamp: latest_ms_timestamp,
tangle_time,
});
}
}
Expand Down
8 changes: 4 additions & 4 deletions sdk/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,9 @@ pub struct NetworkInfo {
/// Protocol parameters.
#[serde(default)]
pub protocol_parameters: ProtocolParameters,
/// The latest cached milestone timestamp.
/// The current tangle time.
#[serde(skip)]
pub latest_milestone_timestamp: Option<u32>,
pub tangle_time: Option<u64>,
}

impl NetworkInfo {
Expand All @@ -274,8 +274,8 @@ impl NetworkInfo {
self
}

pub fn with_latest_milestone_timestamp(mut self, latest_milestone_timestamp: impl Into<Option<u32>>) -> Self {
self.latest_milestone_timestamp = latest_milestone_timestamp.into();
pub fn with_tangle_time(mut self, tangle_time: u64) -> Self {
self.tangle_time = Some(tangle_time.into());
self
}
}
19 changes: 9 additions & 10 deletions sdk/src/client/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use {
};

#[cfg(target_family = "wasm")]
use crate::client::constants::CACHE_NETWORK_INFO_TIMEOUT_IN_SECONDS;
use crate::{client::constants::CACHE_NETWORK_INFO_TIMEOUT_IN_SECONDS, types::block::PROTOCOL_VERSION};
use crate::{
client::{
builder::{ClientBuilder, NetworkInfo},
Expand Down Expand Up @@ -109,7 +109,11 @@ impl ClientInner {
}
let info = self.get_info().await?.node_info;
let mut client_network_info = self.network_info.write().await;
client_network_info.protocol_parameters = info.protocol.clone();
client_network_info.protocol_parameters = info
.protocol_parameters_by_version(PROTOCOL_VERSION)
.expect("missing v3 protocol parameters")
.parameters
.clone();

*LAST_SYNC.lock().unwrap() = Some(current_time + CACHE_NETWORK_INFO_TIMEOUT_IN_SECONDS);
}
Expand All @@ -124,7 +128,7 @@ impl ClientInner {

/// Gets the protocol version of the node we're connecting to.
pub async fn get_protocol_version(&self) -> Result<u8> {
Ok(self.get_network_info().await?.protocol_parameters.protocol_version())
Ok(self.get_network_info().await?.protocol_parameters.version())
}

/// Gets the network name of the node we're connecting to.
Expand All @@ -139,17 +143,12 @@ impl ClientInner {

/// Gets the bech32 HRP of the node we're connecting to.
pub async fn get_bech32_hrp(&self) -> Result<Hrp> {
Ok(*self.get_network_info().await?.protocol_parameters.bech32_hrp())
}

/// Gets the below maximum depth of the node we're connecting to.
pub async fn get_below_max_depth(&self) -> Result<u8> {
Ok(self.get_network_info().await?.protocol_parameters.below_max_depth())
Ok(self.get_network_info().await?.protocol_parameters.bech32_hrp())
}

/// Gets the rent structure of the node we're connecting to.
pub async fn get_rent_structure(&self) -> Result<RentStructure> {
Ok(*self.get_network_info().await?.protocol_parameters.rent_structure())
Ok(self.get_network_info().await?.protocol_parameters.rent_structure())
}

/// Gets the token supply of the node we're connecting to.
Expand Down
10 changes: 4 additions & 6 deletions sdk/src/client/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,13 @@ pub enum Error {
/// Tokio task join error
#[error("{0}")]
TaskJoin(#[from] tokio::task::JoinError),
/// Local time doesn't match the time of the latest milestone timestamp
#[error(
"local time {current_time} doesn't match the time of the latest milestone timestamp: {milestone_timestamp}"
)]
/// Local time doesn't match the network time
#[error("local time {current_time} doesn't match the tangle time: {tangle_time}")]
TimeNotSynced {
/// The local time.
current_time: u32,
/// The timestamp of the latest milestone.
milestone_timestamp: u32,
/// The tangle time.
tangle_time: u32,
},
/// The semantic validation of a transaction failed.
#[error("the semantic validation of a transaction failed with conflict reason: {} - {0:?}", *.0 as u8)]
Expand Down
22 changes: 16 additions & 6 deletions sdk/src/client/node_manager/syncing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#[cfg(not(target_family = "wasm"))]
use {
crate::types::api::core::response::InfoResponse,
crate::types::block::PROTOCOL_VERSION,
std::{collections::HashSet, time::Duration},
tokio::time::sleep,
};
Expand Down Expand Up @@ -73,13 +74,18 @@ impl ClientInner {
match crate::client::Client::get_node_info(node.url.as_ref(), node.auth.clone()).await {
Ok(info) => {
if info.status.is_healthy || ignore_node_health {
match network_nodes.get_mut(info.protocol.network_name()) {
// Unwrap: We should always have parameters for this version. If we don't we can't recover.
let network_name = info
.protocol_parameters_by_version(PROTOCOL_VERSION)
.expect("missing v3 protocol parameters")
.parameters
.network_name();
match network_nodes.get_mut(network_name) {
Some(network_node_entry) => {
network_node_entry.push((info, node.clone()));
}
None => {
network_nodes
.insert(info.protocol.network_name().to_owned(), vec![(info, node.clone())]);
network_nodes.insert(network_name.to_owned(), vec![(info, node.clone())]);
}
}
} else {
Expand All @@ -105,9 +111,13 @@ impl ClientInner {
if let Some((info, _node_url)) = nodes.first() {
let mut network_info = self.network_info.write().await;

// TODO change to one of the new timestamps, which ones ?
// network_info.latest_milestone_timestamp = info.status.latest_milestone.timestamp;
network_info.protocol_parameters = info.protocol.clone();
network_info.tangle_time = info.status.relative_accepted_tangle_time;
// Unwrap: We should always have parameters for this version. If we don't we can't recover.
network_info.protocol_parameters = info
.protocol_parameters_by_version(PROTOCOL_VERSION)
.expect("missing v3 protocol parameters")
.parameters
.clone();
}

for (info, node_url) in nodes {
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/client/secret/ledger_nano.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ fn merge_unlocks(
// address already at this point, because the reference index needs to be lower
// than the current block index
if !input_address.is_ed25519() {
return Err(Error::MissingInputWithEd25519Address)?;
return Err(Error::MissingInputWithEd25519Address);
}

let unlock = unlocks.next().ok_or(Error::MissingInputWithEd25519Address)?;
Expand All @@ -561,7 +561,7 @@ fn merge_unlocks(
let Signature::Ed25519(ed25519_signature) = signature_unlock.signature();
let ed25519_address = match input_address {
Address::Ed25519(ed25519_address) => ed25519_address,
_ => return Err(Error::MissingInputWithEd25519Address)?,
_ => return Err(Error::MissingInputWithEd25519Address),
};
ed25519_signature.is_valid(&hashed_essence, &ed25519_address)?;
}
Expand Down
Loading

0 comments on commit e86789a

Please sign in to comment.