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

fix(inx): fix ledger output rent structure logic #759

Merged
merged 9 commits into from Sep 30, 2022
3 changes: 1 addition & 2 deletions src/db/collections/outputs/mod.rs
Expand Up @@ -81,7 +81,6 @@ impl From<&LedgerOutput> for OutputDocument {
fn from(rec: &LedgerOutput) -> Self {
let address = rec.output.owning_address().copied();
let is_trivial_unlock = rec.output.is_trivial_unlock();
let rent_structure = rec.output.rent_structure();

Self {
output_id: rec.output_id,
Expand All @@ -94,7 +93,7 @@ impl From<&LedgerOutput> for OutputDocument {
details: OutputDetails {
address,
is_trivial_unlock,
rent_structure,
rent_structure: rec.rent_structure,
},
}
}
Expand Down
54 changes: 51 additions & 3 deletions src/types/ledger/output_metadata.rs
Expand Up @@ -43,6 +43,7 @@ pub struct LedgerOutput {
pub block_id: BlockId,
pub booked: MilestoneIndexTimestamp,
pub output: Output,
pub rent_structure: RentStructureBytes,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
Expand All @@ -56,8 +57,32 @@ impl TryFrom<bee_inx::LedgerOutput> for LedgerOutput {
type Error = bee_inx::Error;

fn try_from(value: bee_inx::LedgerOutput) -> Result<Self, Self::Error> {
use bee_block_stardust::output::{Rent, RentStructureBuilder};
let bee_output = value.output.inner_unverified()?;
let num_data_bytes = {
let config = RentStructureBuilder::new()
.byte_cost(1)
.data_factor(1)
.key_factor(0)
.finish();
bee_output.rent_cost(&config)
};

let num_key_bytes = {
let config = RentStructureBuilder::new()
.byte_cost(1)
.data_factor(0)
.key_factor(1)
.finish();
bee_output.rent_cost(&config)
};

Ok(Self {
output: Into::into(&value.output.inner_unverified()?),
rent_structure: RentStructureBytes {
num_data_bytes,
num_key_bytes,
},
output: Into::into(&bee_output),
output_id: value.output_id.into(),
block_id: value.block_id.into(),
booked: MilestoneIndexTimestamp {
Expand All @@ -76,8 +101,31 @@ impl crate::types::context::TryFromWithContext<bee_inx::LedgerOutput> for Ledger
ctx: &bee_block_stardust::protocol::ProtocolParameters,
value: bee_inx::LedgerOutput,
) -> Result<Self, Self::Error> {
use bee_block_stardust::output::{Rent, RentStructureBuilder};
let bee_output = value.output.inner(ctx)?;
let num_data_bytes = {
let config = RentStructureBuilder::new()
.byte_cost(1)
.data_factor(1)
.key_factor(0)
.finish();
bee_output.rent_cost(&config)
};

let num_key_bytes = {
let config = RentStructureBuilder::new()
.byte_cost(1)
.data_factor(0)
.key_factor(1)
.finish();
bee_output.rent_cost(&config)
};
Ok(Self {
output: Into::into(&value.output.inner(ctx)?),
rent_structure: RentStructureBytes {
num_data_bytes,
num_key_bytes,
},
output: Into::into(&bee_output),
output_id: value.output_id.into(),
block_id: value.block_id.into(),
booked: MilestoneIndexTimestamp {
Expand Down Expand Up @@ -132,7 +180,7 @@ impl crate::types::context::TryFromWithContext<bee_inx::LedgerSpent> for LedgerS
}

/// The different number of bytes that are used for computing the rent cost.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct RentStructureBytes {
/// The number of key bytes in an output.
pub num_key_bytes: u64,
Expand Down
45 changes: 1 addition & 44 deletions src/types/stardust/block/output/mod.rs
Expand Up @@ -14,7 +14,7 @@ pub mod treasury;

use std::{borrow::Borrow, str::FromStr};

use bee_block_stardust::output::{self as bee, Rent};
use bee_block_stardust::output as bee;
use mongodb::bson::{doc, Bson};
use serde::{Deserialize, Serialize};

Expand All @@ -30,7 +30,6 @@ pub use self::{
use super::Address;
use crate::types::{
context::{TryFromWithContext, TryIntoWithContext},
ledger::RentStructureBytes,
stardust::block::payload::transaction::TransactionId,
};

Expand Down Expand Up @@ -153,48 +152,6 @@ impl Output {
Self::Foundry(_) => true,
}
}

pub fn rent_structure(&self) -> RentStructureBytes {
// Computing the rent structure is independent of the protocol parameters, we just need this for conversion.
let ctx = bee_block_stardust::protocol::protocol_parameters();
match self {
output @ (Self::Basic(_) | Self::Alias(_) | Self::Foundry(_) | Self::Nft(_)) => {
let bee_output = bee::Output::try_from_with_context(&ctx, output.clone())
.expect("`Output` has to be convertible to `bee::Output`");

// The following computations of `data_bytes` and `key_bytes` makec use of the fact that the byte cost
// computation is a linear combination with respect to the type of the fields and their weight.

let num_data_bytes = {
let config = bee::RentStructureBuilder::new()
.byte_cost(1)
.data_factor(1)
.key_factor(0)
.finish();
bee_output.rent_cost(&config)
};

let num_key_bytes = {
let config = bee::RentStructureBuilder::new()
.byte_cost(1)
.data_factor(0)
.key_factor(1)
.finish();
bee_output.rent_cost(&config)
};

RentStructureBytes {
num_data_bytes,
num_key_bytes,
}
}
// The treasury output does not have an associated byte cost.
Self::Treasury(_) => RentStructureBytes {
num_key_bytes: 0,
num_data_bytes: 0,
},
}
}
}

impl<T: Borrow<bee::Output>> From<T> for Output {
Expand Down
9 changes: 8 additions & 1 deletion tests/blocks.rs
Expand Up @@ -9,7 +9,10 @@ mod test_rand {
use chronicle::{
db::collections::{BlockCollection, OutputCollection},
types::{
ledger::{BlockMetadata, ConflictReason, LedgerInclusionState, LedgerOutput, MilestoneIndexTimestamp},
ledger::{
BlockMetadata, ConflictReason, LedgerInclusionState, LedgerOutput, MilestoneIndexTimestamp,
RentStructureBytes,
},
stardust::block::{output::OutputId, payload::TransactionEssence, Block, BlockId, Payload},
},
};
Expand Down Expand Up @@ -73,6 +76,10 @@ mod test_rand {
milestone_index: 0.into(),
milestone_timestamp: 12345.into(),
},
rent_structure: RentStructureBytes {
num_key_bytes: 0,
num_data_bytes: 100,
},
output,
}))
.await
Expand Down
6 changes: 5 additions & 1 deletion tests/claiming.rs
Expand Up @@ -9,7 +9,7 @@ mod test_rand {
use chronicle::{
db::collections::OutputCollection,
types::{
ledger::{LedgerOutput, LedgerSpent, MilestoneIndexTimestamp, SpentMetadata},
ledger::{LedgerOutput, LedgerSpent, MilestoneIndexTimestamp, RentStructureBytes, SpentMetadata},
stardust::block::{
output::{BasicOutput, OutputAmount, OutputId},
payload::TransactionId,
Expand Down Expand Up @@ -37,6 +37,10 @@ mod test_rand {
let unspent_outputs = (1..=5)
.map(|i| LedgerOutput {
output_id: OutputId::rand(),
rent_structure: RentStructureBytes {
num_key_bytes: 0,
num_data_bytes: 100,
},
output: rand_output_with_value(i.into()),
block_id: BlockId::rand(),
booked: MilestoneIndexTimestamp {
Expand Down
6 changes: 5 additions & 1 deletion tests/outputs.rs
Expand Up @@ -9,7 +9,7 @@ mod test_rand {
use chronicle::{
db::collections::{OutputCollection, OutputMetadataResult, OutputWithMetadataResult},
types::{
ledger::{LedgerOutput, LedgerSpent, MilestoneIndexTimestamp, SpentMetadata},
ledger::{LedgerOutput, LedgerSpent, MilestoneIndexTimestamp, RentStructureBytes, SpentMetadata},
stardust::block::{output::OutputId, payload::TransactionId, BlockId, Output},
},
};
Expand All @@ -29,6 +29,10 @@ mod test_rand {
.take(100)
.map(|output| LedgerOutput {
output_id: OutputId::rand(),
rent_structure: RentStructureBytes {
num_key_bytes: 0,
num_data_bytes: 100,
},
output,
block_id: BlockId::rand(),
booked: MilestoneIndexTimestamp {
Expand Down