Skip to content

Commit ea1927d

Browse files
committed
Merge branch 'development' into tm/upgrade-ledger-2fa
2 parents d724140 + 099d509 commit ea1927d

File tree

11 files changed

+408
-269
lines changed

11 files changed

+408
-269
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
id: managed-decimal
3+
title: Managed Decimal
4+
---
5+
6+
[comment]: # (mx-context-auto)
7+
8+
## Managed Decimal Overview
9+
10+
`ManagedDecimal` is a generic type representing a fixed-point decimal number managed by the API.
11+
It is designed to handle decimal values with a specific number of decimals, providing operations such as addition, subtraction, multiplication, division, scaling, and conversion between different decimal precision and also more complex operations such as logarithm and nth root with a customizable degree of precision.
12+
13+
Essentially, `ManagedDecimal` is simply a struct containing a wrapper over a `BigIntHandle` (`BigUint`) and the number of decimals associated with that value (precision). Having such a light design helps `ManagedDecimal` become the optimal solution for dealing with fixed-point decimal numbers in terms of efficiency and readability.
14+
15+
```rust title=managed_decimal.rs
16+
#[derive(Debug, Clone)]
17+
pub struct ManagedDecimal<M: ManagedTypeApi, D: Decimals> {
18+
data: BigUint<M>, // value * scaling_factor
19+
decimals: D, // number_of_decimals (precision)
20+
}
21+
```
22+
23+
The `scaling factor` of the decimal is `10^num_of_decimals` and is a cached value across multiple `ManagedDecimal` instances for increased efficiency.
24+
25+
```rust title=example.rs
26+
pub fn main() {
27+
let decimal = ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(1u64));
28+
let cached_decimal = ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(5u64));
29+
}
30+
```
31+
32+
[comment]: # (mx-context-auto)
33+
34+
## Number of decimals
35+
36+
`Decimals` is a trait representing the number of decimals associated with a decimal value and is only
37+
implemented for `NumDecimals` and `ConstDecimals`.
38+
`NumDecimals` is a type alias for `usize` and is used to specify the number of decimals dynamically, while `ConstDecimals` is a type that represents a constant number of decimals and is used to statically specify the number of decimals for ManagedDecimal instances.
39+
40+
```rust title=example.rs
41+
pub fn main() {
42+
let decimal: ManagedDecimal<StaticApi, NumDecimals> = ManagedDecimal::from_raw_units(BigUint::from(100u64), 2usize);
43+
let const_decimal = ManagedDecimal::<StaticApi, ConstDecimals<3>>::const_decimals_from_raw(BigUint::from(500u64))
44+
}
45+
```
46+
47+
[comment]: # (mx-context-auto)
48+
49+
## Operations
50+
51+
`ManagedDecimal` supports various types of simple and complex operations, as well as conversions and scaling. More code examples can be found at `mx-sdk-rs/framework/scenario/tests/managed_decimal_test.rs`
52+
53+
### Available methods:
54+
- Simple Operations:
55+
- `add`, `mul`, `div`, `sub` are all implemented for `ConstDecimals` of the same scale.
56+
```rust title=example.rs
57+
pub fn main() {
58+
let fixed = ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(1u64));
59+
let fixed_2 = ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(5u64));
60+
61+
let addition = fixed + fixed_2;
62+
assert_eq!(
63+
addition,
64+
ManagedDecimal::<StaticApi, ConstDecimals<2>>::from(BigUint::from(6u64))
65+
);
66+
}
67+
```
68+
- `trunc(&self) -> BigUint<M>` returns the `data` field without the `scaling_factor` applied, by dividing the value to the scaling factor and truncating.
69+
```rust title=example.rs
70+
pub fn main() {
71+
...
72+
assert_eq!(addition.trunc(), BigUint::from(6u64));
73+
}
74+
```
75+
- Complex Operations:
76+
- `log<T: Decimals>(self, target_base: BigUint<M>, precision: T) -> ManagedDecimal<M, T>` returns the value of log in any base with customizable precision level.
77+
```rust title=example.rs
78+
pub fn logarithm() {
79+
let fixed = ManagedDecimal::<StaticApi, NumDecimals>::from_raw_units(BigUint::from(10u64), 1usize);
80+
let fixed_const = ManagedDecimal::<StaticApi, ConstDecimals<1>>::const_decimals_from_raw(BigUint::from(10u64));
81+
82+
let log2_fixed = fixed.log(BigUint::from(2u64), 10_000usize);
83+
assert_eq!(
84+
log2_fixed,
85+
ManagedDecimal::<StaticApi, NumDecimals>::from_raw_units(BigUint::from(33219u64), 10_000usize)
86+
);
87+
}
88+
```
89+
- Scaling:
90+
- `scale(&self) -> usize` returns the number of decimals (the scale).
91+
- `scaling_factor<M: ManagedTypeApi>(&self) -> BigUint<M>` returns the scaling factor value (`10^num_decimals`).
92+
- `rescale<T: Decimals>(self, scale_to: T) -> ManagedDecimal<M, T>` returns the correspondent of the decimal in the newly specified scale. It can also convert between `NumDecimal` and `ConstDecimals` instances.
93+
94+
```rust title=example.rs
95+
pub fn main() {
96+
...
97+
let fixed_8: ManagedDecimal<StaticApi, NumDecimals> = ManagedDecimal::from_raw_units(BigUint::from(5u64), 5usize);
98+
let fixed_9 = fixed_8.rescale(ConstDecimals::<3>);
99+
assert_eq!(
100+
fixed_9,
101+
ManagedDecimal::<StaticApi, ConstDecimals<3>>::const_decimals_from_raw(BigUint::from(500u64))
102+
);
103+
}
104+
```
105+
- Conversions:
106+
- `into_raw_units(&self) -> &BigUint<M>` returns the `data` field value.
107+
108+
```rust title=example.rs
109+
pub fn main() {
110+
...
111+
assert_eq!(addition.into_raw_units(), &BigUint::from(600u64));
112+
}
113+
```
114+
- `from_raw_units(data: BigUint<M>, decimals: D) -> Self` returns a `ManagedDecimal` from a data field value without applying scaling factor.
115+
116+
```rust title=example.rs
117+
pub fn main() {
118+
...
119+
let fixed_4: ManagedDecimal<StaticApi, NumDecimals> = ManagedDecimal::from_raw_units(BigUint::from(100u64), 2usize);
120+
let fixed_5 = fixed_4.rescale(2usize);
121+
assert_eq!(
122+
fixed_5,
123+
ManagedDecimal::from_raw_units(BigUint::from(100000000u64), 8usize)
124+
);
125+
}
126+
```
127+
- `const_decimals_from_raw(data: BigUint<M>) -> Self` returns a `ConstDecimals` type of `ManagedDecimal` from a data field value without applying scaling factor.
128+
```rust title=example.rs
129+
pub fn main() {
130+
...
131+
let fixed_const: ManagedDecimal<StaticApi, ConstDecimals<1>> = ManagedDecimal::const_decimals_from_raw(BigUint::from(1u64));
132+
}
133+
```
134+
- `num_decimals(&self) -> NumDecimals` returns the number of decimals.
135+
- `to_big_float(&self) -> BigFloat<M>` returns the decimal as `BigFloat<M>`.
136+
- `to_big_int(self) -> BigInt<M>` returns the decimal as `BigInt`.
137+
- `from_big_int<T: Decimals>(big_int: BigInt<M>, num_decimals: T) -> ManagedDecimal<M, T>` constructs a `ManagedDecimal` from a `BigInt` with customizable `num_decimals`.
138+
- `from_big_float<T: Decimals>(big_float: BigFloat<M>, num_decimals: T) -> ManagedDecimal<M, T>` constructs a `ManagedDecimal` from a `BigFloat` with customizable `num_decimals`.
139+
```rust title=example.rs
140+
pub fn main() {
141+
...
142+
let float_1 = BigFloat::<StaticApi>::from_frac(3i64, 2i64);
143+
let fixed_float_1 = ManagedDecimal::<StaticApi, ConstDecimals<1>>::from_big_float(float_1.clone(),ConstDecimals::<1>);
144+
let fixed_float_2 = ManagedDecimal::<StaticApi, NumDecimals>::from_big_float(float_1, 1usize);
145+
146+
assert_eq!(
147+
fixed_float_1,
148+
ManagedDecimal::<StaticApi, ConstDecimals<1>>::const_decimals_from_raw(BigUint::from(15u64))
149+
);
150+
assert_eq!(
151+
fixed_float_2,
152+
ManagedDecimal::<StaticApi, NumDecimals>::from_raw_units(BigUint::from(15u64), 1usize)
153+
);
154+
}
155+
```

docs/integrators/deep-history-squad.md

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -117,46 +117,16 @@ Apart from the flag mentioned above, the setup of a deep-history observer is ide
117117
Never attach a non-pruned database to a regular observer (i.e. that does not have the above **operation-mode**) - unless you are not interested into the deep-history features. The regular observer irremediably removes, trucates and prunes the data (as configured, for storage efficiency).
118118
:::
119119

120-
Now that we have finished with the installation part, we can proceed with populating the database from a non-pruned database archive. There are two options here:
121-
- Download non-pruned database
122-
- Reconstruct non-pruned database
120+
Now that we have finished with the installation part, we can proceed to populate the non-pruned database. There are two options here:
121+
- Reconstruct non-pruned database (recommended).
122+
- Download non-pruned database (we can provide archives for the required epochs, on request).
123123

124-
[comment]: # (mx-context-auto)
125-
126-
## Downloading non-pruned database
127-
128-
Archives supporting historical lookup are available to download from a Google Cloud Storage [bucket](https://console.cloud.google.com/storage/browser/multiversx-deep-history-archives-mainnet).
129-
130-
In order to avoid unintentional downloads and promote careful fetching of archives, we've enabled the [requester pays](https://cloud.google.com/storage/docs/requester-pays) feature on the bucket that holds the deep-history archives for mainnet.
131-
132-
### Requirements
133-
134-
1. **Google Cloud Platform Account**: An account on Google Cloud Platform with billing enabled is required. Find out how you can manage your billing account and modify your project here:
135-
- https://cloud.google.com/billing/docs/how-to/manage-billing-account
136-
- https://cloud.google.com/billing/docs/how-to/modify-project
137-
138-
2. **Google Cloud SDK**: The Google Cloud SDK includes the `gcloud` command-line tool, which you'll use to interact with Google Cloud Storage. In order to install it, please follow the instructions provided on the [Google Cloud SDK webpage](https://cloud.google.com/sdk/docs/install).
139-
140-
### Downloading archives
141-
142-
Once you have the Google Cloud SDK installed and you're [authenticated](https://cloud.google.com/docs/authentication/gcloud), you can download archives from the Google Cloud Storage bucket using the `gcloud storage cp` command.
143-
144-
Here's an example command that downloads an archive from the `multiversx-deep-history-archives-mainnet` bucket:
145-
```
146-
gcloud storage cp gs://multiversx-deep-history-archives-mainnet/shard-0/Epoch_01200.tar ~/DOWNLOAD_LOCATION --billing-project=BILLING_PROJECT
147-
```
148-
Replace **BILLING_PROJECT** with the name of your billing project and **~/DOWNLOAD_LOCATION** with the directory where the archives should be downloaded.
149-
150-
The following example will download epochs starting with Epoch_01000.tar up to Epoch_01300.tar, for a billing project called **multiversx**:
151-
```
152-
gcloud storage cp gs://multiversx-deep-history-archives-mainnet/shard-0/Epoch_0{1000..1300}.tar ~/Downloads/ --billing-project=multiversx
153-
```
154124

155125
[comment]: # (mx-context-auto)
156126

157127
## Reconstructing non-pruned databases
158128

159-
An alternative to downloading the non-pruned history is to reconstruct it locally (on your own infrastructure).
129+
The recommended method for populating a non-pruned database is to reconstruct it locally (on your own infrastructure).
160130

161131
There are also two options for reconstructing a non-pruned database:
162132
- Based on the **[import-db](/validators/import-db/)** feature, which re-processes past blocks - and, while doing so, retains the whole, non-pruned accounts history.

0 commit comments

Comments
 (0)