Skip to content

Commit 5fa5fe1

Browse files
authored
Merge pull request #4573 from anoma/murisi/shielded-rewards-example
Added an example program to derive constraints on shielded reward parameters
2 parents 11e849d + 0b3ae12 commit 5fa5fe1

File tree

5 files changed

+663
-3
lines changed

5 files changed

+663
-3
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Added Cargo example that derives bounds on shielded reward parameters to
2+
ensure non-zero rewards ([\#4573](https://github.com/anoma/namada/pull/4573))

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/core/src/token.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ impl DenominatedAmount {
512512
}
513513
}
514514

515-
/// Attempt to increase the precision of an amount. Can fail
516-
/// if the resulting amount does not fit into 256 bits.
515+
/// Return an equivalent denominated amount with the given denomination. Can
516+
/// fail if the resulting amount does not fit into 256 bits.
517517
pub fn increase_precision(
518518
self,
519519
denom: Denomination,
@@ -534,8 +534,43 @@ impl DenominatedAmount {
534534
.ok_or(AmountParseError::PrecisionOverflow)
535535
}
536536

537+
/// Return the closest denominated amount with the given denomination and
538+
/// the error.
539+
pub fn approximate(
540+
self,
541+
denom: Denomination,
542+
) -> Result<(Self, Self), AmountParseError> {
543+
if denom.0 < self.denom.0 {
544+
// Divide numerator and denominator by a power of 10
545+
let amount = self.amount.raw_amount();
546+
#[allow(clippy::arithmetic_side_effects)]
547+
let (quot, rem) = Uint::from(10)
548+
.checked_pow(Uint::from(self.denom.0 - denom.0))
549+
.and_then(|scaling| {
550+
amount.checked_div(scaling).zip(amount.checked_rem(scaling))
551+
})
552+
.ok_or(AmountParseError::PrecisionOverflow)?;
553+
let approx = Self {
554+
amount: quot.into(),
555+
denom,
556+
};
557+
let error = Self {
558+
amount: rem.into(),
559+
denom: self.denom,
560+
};
561+
Ok((approx, error))
562+
} else {
563+
// Multiply numerator and denominator by a power of 10
564+
let error = Self {
565+
amount: 0.into(),
566+
denom: self.denom,
567+
};
568+
self.increase_precision(denom).map(|x| (x, error))
569+
}
570+
}
571+
537572
/// Create a new [`DenominatedAmount`] with the same underlying
538-
/// amout but a new denomination.
573+
/// amount but a new denomination.
539574
pub fn redenominate(self, new_denom: u8) -> Self {
540575
Self {
541576
amount: self.amount,
@@ -590,6 +625,38 @@ impl DenominatedAmount {
590625
})
591626
}
592627

628+
/// Checked division computed to the given precision. Returns `None` on
629+
/// overflow.
630+
pub fn checked_div_precision(
631+
&self,
632+
rhs: DenominatedAmount,
633+
denom: Denomination,
634+
) -> Option<Self> {
635+
#[allow(clippy::arithmetic_side_effects)]
636+
let pow = i16::from(rhs.denom.0) + i16::from(denom.0)
637+
- i16::from(self.denom.0);
638+
if pow < 0 {
639+
return None;
640+
}
641+
let amount = Uint::from(10).checked_pow(Uint::from(pow)).and_then(
642+
|scaling| {
643+
scaling.checked_mul_div(
644+
self.amount.raw_amount(),
645+
rhs.amount.raw_amount(),
646+
)
647+
},
648+
)?;
649+
Some(Self {
650+
amount: amount.0.into(),
651+
denom,
652+
})
653+
}
654+
655+
/// Checked division. Returns `None` on overflow.
656+
pub fn checked_div(&self, rhs: DenominatedAmount) -> Option<Self> {
657+
self.checked_div_precision(rhs, self.denom)
658+
}
659+
593660
/// Returns the significand of this number
594661
pub const fn amount(&self) -> Amount {
595662
self.amount

examples/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ version.workspace = true
1616
name = "generate-txs"
1717
path = "generate_txs.rs"
1818

19+
[[example]]
20+
name = "shielded-rewards"
21+
path = "shielded_rewards.rs"
22+
1923
[[example]]
2024
name = "tx-schema"
2125
path = "tx_schema.rs"
@@ -52,6 +56,8 @@ borsh.workspace = true
5256
data-encoding.workspace = true
5357
linkme.workspace = true
5458
proptest.workspace = true
59+
serde.workspace = true
5560
serde_json.workspace = true
5661
sha2.workspace = true
5762
tokio = { workspace = true, default-features = false }
63+
toml.workspace = true

0 commit comments

Comments
 (0)