Skip to content

Commit 0b4bb28

Browse files
mootz12sisureshCopilotclaudedmkozh
authored
Update to v26 and add support for CAP-73, 78, 79, 80 and 82 (#1814)
### What * Update soroban-env dependencies to p26 * Add support for CAP-78 host functions to perform limited TTL extensions on contract data and code entries (#1807) * Add support for CAP-82 host functions to perform checked math on 256-bit integer types (#1801) * Add `min_value` and `max_value` functions on 256-bit integer types (#1823) * Add support for CAP-79 (muxed address strkey conversion host functions) and CAP-80 (Additional BN254 and BLS12-381 host functions) (#1745) * Add support for CAP-73 Stellar Asset Contract `trust()` function (#1801) ### Why Update SDK to support new features in protocol 26. ### Known limitations None --------- Co-authored-by: Siddharth Suresh <siddharth@stellar.org> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sisuresh <5050166+sisuresh@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Dmytro Kozhevin <dmytro@stellar.org> Co-authored-by: Jay Geng <jay@stellar.org> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent e50d95a commit 0b4bb28

File tree

215 files changed

+2620
-690
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

215 files changed

+2620
-690
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,42 @@ members = [
1515
]
1616

1717
[workspace.package]
18-
version = "25.3.1"
18+
version = "26.0.0-rc.1"
1919
rust-version = "1.91.0"
2020

2121
[workspace.dependencies]
22-
soroban-sdk = { version = "25.3.1", path = "soroban-sdk" }
23-
soroban-sdk-macros = { version = "25.3.1", path = "soroban-sdk-macros" }
24-
soroban-meta = { version = "25.3.1", path = "soroban-meta" }
25-
soroban-spec = { version = "25.3.1", path = "soroban-spec" }
26-
soroban-spec-rust = { version = "25.3.1", path = "soroban-spec-rust" }
27-
soroban-ledger-snapshot = { version = "25.3.1", path = "soroban-ledger-snapshot" }
28-
soroban-token-sdk = { version = "25.3.1", path = "soroban-token-sdk" }
29-
soroban-token-spec = { version = "25.3.1", path = "soroban-token-spec" }
30-
stellar-asset-spec = { version = "25.3.1", path = "stellar-asset-spec" }
22+
soroban-sdk = { version = "26.0.0-rc.1", path = "soroban-sdk" }
23+
soroban-sdk-macros = { version = "26.0.0-rc.1", path = "soroban-sdk-macros" }
24+
soroban-meta = { version = "26.0.0-rc.1", path = "soroban-meta" }
25+
soroban-spec = { version = "26.0.0-rc.1", path = "soroban-spec" }
26+
soroban-spec-rust = { version = "26.0.0-rc.1", path = "soroban-spec-rust" }
27+
soroban-ledger-snapshot = { version = "26.0.0-rc.1", path = "soroban-ledger-snapshot" }
28+
soroban-token-sdk = { version = "26.0.0-rc.1", path = "soroban-token-sdk" }
29+
soroban-token-spec = { version = "26.0.0-rc.1", path = "soroban-token-spec" }
30+
stellar-asset-spec = { version = "26.0.0-rc.1", path = "stellar-asset-spec" }
3131

3232
[workspace.dependencies.soroban-env-common]
33-
version = "=25.0.1"
33+
version = "=26.0.1"
3434
# git = "https://github.com/stellar/rs-soroban-env"
35-
# rev = "cf58d535ab05d02802a5e804a95524650f8c62c7"
35+
# rev = "f4d7b3299df8fc19e92769d0a26be2d032b78ccb"
3636

3737
[workspace.dependencies.soroban-env-guest]
38-
version = "=25.0.1"
38+
version = "=26.0.1"
3939
# git = "https://github.com/stellar/rs-soroban-env"
40-
# rev = "cf58d535ab05d02802a5e804a95524650f8c62c7"
40+
# rev = "f4d7b3299df8fc19e92769d0a26be2d032b78ccb"
4141

4242
[workspace.dependencies.soroban-env-host]
43-
version = "=25.0.1"
43+
version = "=26.0.1"
4444
# git = "https://github.com/stellar/rs-soroban-env"
45-
# rev = "cf58d535ab05d02802a5e804a95524650f8c62c7"
45+
# rev = "f4d7b3299df8fc19e92769d0a26be2d032b78ccb"
4646

4747
[workspace.dependencies.stellar-strkey]
4848
version = "=0.0.16"
4949

5050
[workspace.dependencies.stellar-xdr]
51-
version = "=25.0.0"
51+
version = "=26.0.0"
52+
# git = "https://github.com/stellar/rs-stellar-xdr"
53+
# rev = "dd7a165a193126fd37a751d867bee1cb8f3b55a6"
5254
default-features = false
5355
features = ["curr"]
5456

deny.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,8 @@ deny = [
219219

220220
# Certain crates/versions that will be skipped when doing duplicate detection.
221221
skip = [
222-
{ name = "hashbrown", version = "=0.13.2" },
222+
{ name = "hashbrown", version = "=0.14.5" },
223223
{ name = "stellar-strkey", version = "=0.0.13" },
224-
{ name = "syn", version = "=1.0.109" },
225224
]
226225
# Similarly to `skip` allows you to skip certain crates during duplicate
227226
# detection. Unlike skip, it also includes the entire tree of transitive

soroban-ledger-snapshot/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ impl LedgerSnapshot {
260260
impl Default for LedgerSnapshot {
261261
fn default() -> Self {
262262
Self {
263-
protocol_version: 25,
263+
protocol_version: 26,
264264
sequence_number: Default::default(),
265265
timestamp: Default::default(),
266266
network_id: Default::default(),

soroban-sdk-macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ stellar-xdr = { workspace = true, features = ["curr", "std"] }
2222
syn = {version="2.0.77",features=["full"]}
2323
quote = "1.0"
2424
proc-macro2 = "1.0"
25-
itertools = "0.10.5"
25+
itertools = "0.13.0"
2626
darling = "0.20.10"
2727
macro-string = "0.1.4"
2828
sha2 = "0.10.7"

soroban-sdk/src/_migrating.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,40 @@
1+
//! # Migrating from v25 to v26
2+
//!
3+
//! 1. Add support for [CAP-78: Host functions for performing limited TTL extensions](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0078.md).
4+
//! New `extend_ttl_with_limits` methods on [`Persistent`], [`Instance`], and
5+
//! [`Deployer`] provide bounded control over TTL extensions with `min_extension` and
6+
//! `max_extension` parameters.
7+
//!
8+
//! 2. Add support for [CAP-82: Checked 256-bit integer arithmetic host functions](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0082.md).
9+
//! New `checked_*` methods on [`U256`] and [`I256`] (`checked_add`, `checked_sub`,
10+
//! `checked_mul`, `checked_div`, `checked_pow`, `checked_rem_euclid`, `checked_shl`,
11+
//! `checked_shr`) return `Option` instead of panicking on overflow. Also adds
12+
//! `min_value` and `max_value` methods on [`U256`] and [`I256`] to fetch the
13+
//! value bounds of each type.
14+
//!
15+
//! 3. Add support for [CAP-80: Host functions for efficient ZK BN254 use cases](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0080.md).
16+
//! [`BN254`] gains scalar field arithmetic (`Fr` `Add`/`Sub`/`Mul` traits, `pow`, `inv`),
17+
//! multi-scalar multiplication (`g1_msm`), and curve validation (`g1_is_on_curve`).
18+
//! [`BLS12381`] gains `g1_is_on_curve` and `g2_is_on_curve`.
19+
//!
20+
//! 4. Add support for [CAP-79: Host functions for muxed address strkey conversions](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0079.md).
21+
//! New method [`MuxedAddress::to_strkey`] converts muxed addresses to Stellar strkey format.
22+
//!
23+
//! 5. Add support for [CAP-73: Allow SAC to create G-account balances](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0073.md).
24+
//! Update the [`StellarAssetInterface`] to include the new method [`StellarAssetInterface::trust`]. This method creates
25+
//! an unlimited trustline for the contract's asset, if applicable.
26+
//!
27+
//! [`Persistent`]: crate::storage::Persistent
28+
//! [`Instance`]: crate::storage::Instance
29+
//! [`Deployer`]: crate::deploy::Deployer
30+
//! [`U256`]: crate::U256
31+
//! [`I256`]: crate::I256
32+
//! [`MuxedAddress::to_strkey`]: crate::MuxedAddress::to_strkey
33+
//! [`StellarAssetInterface`]: crate::token::StellarAssetInterface
34+
//! [`StellarAssetInterface::trust`]: crate::token::StellarAssetInterface::trust
35+
//! [`BN254`]: crate::crypto::bn254
36+
//! [`BLS12381`]: crate::crypto::bls12_381
37+
//!
138
//! # Migrating from v23 to v25
239
//!
340
//! 1. [`Events::all()` return type changed from `Vec<(Address, Vec<Val>, Val)>` to `ContractEvents`][v25_event_testing].

soroban-sdk/src/crypto/bls12_381.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,14 @@ impl Bls12_381 {
603603
res.into()
604604
}
605605

606+
/// Checks if a G1 point is on the BLS12-381 curve (no subgroup check).
607+
pub fn g1_is_on_curve(&self, point: &G1Affine) -> bool {
608+
let env = self.env();
609+
internal::Env::bls12_381_g1_is_on_curve(env, point.to_object())
610+
.unwrap_infallible()
611+
.into()
612+
}
613+
606614
/// Adds two points `p0` and `p1` in G1.
607615
pub fn g1_add(&self, p0: &G1Affine, p1: &G1Affine) -> G1Affine {
608616
let env = self.env();
@@ -671,6 +679,14 @@ impl Bls12_381 {
671679
res.into()
672680
}
673681

682+
/// Checks if a G2 point is on the BLS12-381 curve (no subgroup check).
683+
pub fn g2_is_on_curve(&self, point: &G2Affine) -> bool {
684+
let env = self.env();
685+
internal::Env::bls12_381_g2_is_on_curve(env, point.to_object())
686+
.unwrap_infallible()
687+
.into()
688+
}
689+
674690
/// Adds two points `p0` and `p1` in G2.
675691
pub fn g2_add(&self, p0: &G2Affine, p1: &G2Affine) -> G2Affine {
676692
let env = self.env();

soroban-sdk/src/crypto/bn254.rs

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
use crate::xdr::ScVal;
33
use crate::{
44
crypto::utils::BigInt,
5-
env::internal::{self, BytesObject, U256Val},
5+
env::internal::{self, BytesObject, U256Val, U64Val},
66
impl_bytesn_repr_without_from_bytes,
77
unwrap::{UnwrapInfallible, UnwrapOptimized},
88
Bytes, BytesN, ConversionError, Env, IntoVal, TryFromVal, Val, Vec, U256,
99
};
1010
use core::{
1111
cmp::Ordering,
1212
fmt::Debug,
13-
ops::{Add, Mul, Neg},
13+
ops::{Add, Mul, Neg, Sub},
1414
};
1515

1616
pub const BN254_FP_SERIALIZED_SIZE: usize = 32; // Size in bytes of a serialized Bn254Fp element in BN254. The field modulus is 254 bits, requiring 32 bytes (256 bits).
@@ -254,6 +254,38 @@ impl Fr {
254254
pub fn to_val(&self) -> Val {
255255
self.0.to_val()
256256
}
257+
258+
pub fn pow(&self, rhs: u64) -> Self {
259+
self.env().crypto().bn254().fr_pow(self, rhs)
260+
}
261+
262+
pub fn inv(&self) -> Self {
263+
self.env().crypto().bn254().fr_inv(self)
264+
}
265+
}
266+
267+
impl Add for Fr {
268+
type Output = Fr;
269+
270+
fn add(self, rhs: Self) -> Self::Output {
271+
self.env().crypto().bn254().fr_add(&self, &rhs)
272+
}
273+
}
274+
275+
impl Sub for Fr {
276+
type Output = Fr;
277+
278+
fn sub(self, rhs: Self) -> Self::Output {
279+
self.env().crypto().bn254().fr_sub(&self, &rhs)
280+
}
281+
}
282+
283+
impl Mul for Fr {
284+
type Output = Fr;
285+
286+
fn mul(self, rhs: Self) -> Self::Output {
287+
self.env().crypto().bn254().fr_mul(&self, &rhs)
288+
}
257289
}
258290

259291
// BN254 scalar field modulus r in big-endian bytes.
@@ -386,6 +418,59 @@ impl Bn254 {
386418
.unwrap_infallible()
387419
.into()
388420
}
421+
422+
/// Performs a multi-scalar multiplication (MSM) operation in G1.
423+
pub fn g1_msm(&self, vp: Vec<Bn254G1Affine>, vs: Vec<Fr>) -> Bn254G1Affine {
424+
let env = self.env();
425+
let bin = internal::Env::bn254_g1_msm(env, vp.into(), vs.into()).unwrap_infallible();
426+
unsafe { Bn254G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
427+
}
428+
429+
/// Checks if a G1 point is on the BN254 curve.
430+
pub fn g1_is_on_curve(&self, point: &Bn254G1Affine) -> bool {
431+
let env = self.env();
432+
internal::Env::bn254_g1_is_on_curve(env, point.to_object())
433+
.unwrap_infallible()
434+
.into()
435+
}
436+
437+
// scalar arithmetic
438+
439+
/// Adds two scalars in the BN254 scalar field `Fr`.
440+
pub fn fr_add(&self, lhs: &Fr, rhs: &Fr) -> Fr {
441+
let env = self.env();
442+
let v = internal::Env::bn254_fr_add(env, lhs.into(), rhs.into()).unwrap_infallible();
443+
U256::try_from_val(env, &v).unwrap_infallible().into()
444+
}
445+
446+
/// Subtracts one scalar from another in the BN254 scalar field `Fr`.
447+
pub fn fr_sub(&self, lhs: &Fr, rhs: &Fr) -> Fr {
448+
let env = self.env();
449+
let v = internal::Env::bn254_fr_sub(env, lhs.into(), rhs.into()).unwrap_infallible();
450+
U256::try_from_val(env, &v).unwrap_infallible().into()
451+
}
452+
453+
/// Multiplies two scalars in the BN254 scalar field `Fr`.
454+
pub fn fr_mul(&self, lhs: &Fr, rhs: &Fr) -> Fr {
455+
let env = self.env();
456+
let v = internal::Env::bn254_fr_mul(env, lhs.into(), rhs.into()).unwrap_infallible();
457+
U256::try_from_val(env, &v).unwrap_infallible().into()
458+
}
459+
460+
/// Raises a scalar to the power of a given exponent in the BN254 scalar field `Fr`.
461+
pub fn fr_pow(&self, lhs: &Fr, rhs: u64) -> Fr {
462+
let env = self.env();
463+
let rhs = U64Val::try_from_val(env, &rhs).unwrap_optimized();
464+
let v = internal::Env::bn254_fr_pow(env, lhs.into(), rhs).unwrap_infallible();
465+
U256::try_from_val(env, &v).unwrap_infallible().into()
466+
}
467+
468+
/// Computes the multiplicative inverse of a scalar in the BN254 scalar field `Fr`.
469+
pub fn fr_inv(&self, lhs: &Fr) -> Fr {
470+
let env = self.env();
471+
let v = internal::Env::bn254_fr_inv(env, lhs.into()).unwrap_infallible();
472+
U256::try_from_val(env, &v).unwrap_infallible().into()
473+
}
389474
}
390475

391476
#[cfg(test)]

soroban-sdk/src/deploy.rs

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@
124124
//! ```
125125
126126
use crate::{
127-
env::internal::Env as _, unwrap::UnwrapInfallible, Address, Bytes, BytesN, ConstructorArgs,
128-
Env, IntoVal,
127+
env::internal::{ContractTtlExtension, Env as _},
128+
unwrap::UnwrapInfallible,
129+
Address, Bytes, BytesN, ConstructorArgs, Env, IntoVal,
129130
};
130131

131132
/// Deployer provides access to deploying contracts.
@@ -272,6 +273,77 @@ impl Deployer {
272273
)
273274
.unwrap_infallible();
274275
}
276+
277+
/// Extend the TTL of the contract instance and code with limits on the extension.
278+
///
279+
/// Extends the TTL of the instance and code to be up to `extend_to` ledgers.
280+
/// The extension only happens if it exceeds `min_extension` ledgers, otherwise
281+
/// this is a no-op. The amount of extension will not exceed `max_extension` ledgers.
282+
///
283+
/// Note that the extension is applied to both the contract code and contract instance,
284+
/// so it's possible that one is extended but not the other depending on their current TTLs.
285+
///
286+
/// The TTL is the number of ledgers between the current ledger and the final ledger
287+
/// the data can still be accessed.
288+
pub fn extend_ttl_with_limits(
289+
&self,
290+
contract_address: Address,
291+
extend_to: u32,
292+
min_extension: u32,
293+
max_extension: u32,
294+
) {
295+
self.env
296+
.extend_contract_instance_and_code_ttl_v2(
297+
contract_address.to_object(),
298+
ContractTtlExtension::InstanceAndCode,
299+
extend_to.into(),
300+
min_extension.into(),
301+
max_extension.into(),
302+
)
303+
.unwrap_infallible();
304+
}
305+
306+
/// Extend the TTL of the contract instance with limits on the extension.
307+
///
308+
/// Same as [`extend_ttl_with_limits`](Self::extend_ttl_with_limits) but only for contract instance.
309+
pub fn extend_ttl_for_contract_instance_with_limits(
310+
&self,
311+
contract_address: Address,
312+
extend_to: u32,
313+
min_extension: u32,
314+
max_extension: u32,
315+
) {
316+
self.env
317+
.extend_contract_instance_and_code_ttl_v2(
318+
contract_address.to_object(),
319+
ContractTtlExtension::Instance,
320+
extend_to.into(),
321+
min_extension.into(),
322+
max_extension.into(),
323+
)
324+
.unwrap_infallible();
325+
}
326+
327+
/// Extend the TTL of the contract code with limits on the extension.
328+
///
329+
/// Same as [`extend_ttl_with_limits`](Self::extend_ttl_with_limits) but only for contract code.
330+
pub fn extend_ttl_for_code_with_limits(
331+
&self,
332+
contract_address: Address,
333+
extend_to: u32,
334+
min_extension: u32,
335+
max_extension: u32,
336+
) {
337+
self.env
338+
.extend_contract_instance_and_code_ttl_v2(
339+
contract_address.to_object(),
340+
ContractTtlExtension::Code,
341+
extend_to.into(),
342+
min_extension.into(),
343+
max_extension.into(),
344+
)
345+
.unwrap_infallible();
346+
}
275347
}
276348

277349
/// A deployer that deploys a contract that has its ID derived from the provided

soroban-sdk/src/env.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub mod internal {
7676
}
7777

7878
pub use internal::xdr;
79+
pub use internal::ContractTtlExtension;
7980
pub use internal::ConversionError;
8081
pub use internal::EnvBase;
8182
pub use internal::Error;

0 commit comments

Comments
 (0)