Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions ci/no_clock_and_no_json.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ common_allow_globs=(
# other operational controls. They remain subject to the JSON/encoding/version gates.
clock_allow_globs=(
"${common_allow_globs[@]}"
--glob '!**/api/infra/rate_limit.rs' # transport-layer DoS rate limiting (permitted)
--glob '!**/api/transport/b0x.rs' # transport-layer rate limiting (permitted)
--glob '!**/jni/ble_events.rs' # BLE event buffering / runtime wakeups
--glob '!**/deterministic_state_machine/dsm_sdk/src/sdk/bluetooth_transport.rs' # BLE retries / ACK timeouts / reconnect backoff
--glob '!**/deterministic_state_machine/dsm_sdk/src/bluetooth/pairing_orchestrator.rs' # BLE handshake freshness / retry windows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ pub const TAG_DSM_SOFI_VAULT_ID: TaggedHashDomain<'static> =
/// indexed (Part II §11).
pub const TAG_DSM_SOFI_VAULT_GENESIS_LOCATOR: TaggedHashDomain<'static> =
crate::tagged_domain!(b"DSM/sofi/vault-genesis-locator/v1");
/// `H(tag ‖ t)` — the locator under which the genesis preimage of every
/// vault whose market pairs token `t` (its policy commit) is indexed, so a
/// vault is found by its tokens (SoFi Amendment S16).
pub const TAG_DSM_SOFI_VAULT_TOKEN_LOCATOR: TaggedHashDomain<'static> =
crate::tagged_domain!(b"DSM/sofi/vault-token-locator/v1");
/// Immutable-store namespace of the EXACT `VaultGenesisPreimage` bytes
/// (Part II §10): `addr = immutable_addr(tag, bytes)`; the reader recomputes
/// it and `vault_id()` from the bytes.
Expand Down Expand Up @@ -204,6 +209,7 @@ pub(crate) const SOFI_TAGS: &[TaggedHashDomain<'static>] = &[
TAG_DSM_SOFI_PREIMAGE_LOCATOR,
TAG_DSM_SOFI_VAULT_ID,
TAG_DSM_SOFI_VAULT_GENESIS_LOCATOR,
TAG_DSM_SOFI_VAULT_TOKEN_LOCATOR,
TAG_DSM_SOFI_VAULT_GENESIS_OBJECT,
TAG_DSM_SOFI_SETUP_OBJECT,
TAG_DSM_SOFI_PRECOMMIT_OBJECT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ mod tests {
// -1 with the client-edited storage node list: its placement seed was the
// network hash domain's only input.
// +1 with the TraderPreBalance object namespace (SoFi Amendment S12).
const EXPECTED_TAG_COUNT: usize = 351;
// +1 with the vault token locator (SoFi Amendment S16).
const EXPECTED_TAG_COUNT: usize = 352;

/// Scan the crate source for every declared domain-tag constant.
///
Expand Down
4 changes: 2 additions & 2 deletions dsm_client/deterministic_state_machine/dsm/src/core/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,10 +592,10 @@ pub fn handle_envelope_universal(env_bytes: &[u8]) -> Vec<u8> {
| gp::envelope::Payload::TokenBurnResponse(_)
| gp::envelope::Payload::TokenFeeScheduleResponse(_)
| gp::envelope::Payload::SofiVaultCreatedResponse(_)
| gp::envelope::Payload::SofiSetupResponse(_)
| gp::envelope::Payload::SofiFindRouteResponse(_)
| gp::envelope::Payload::SofiPositionResponse(_)
| gp::envelope::Payload::SofiRelayResponse(_),
| gp::envelope::Payload::SofiRelayResponse(_)
| gp::envelope::Payload::SofiVaultsResponse(_),
) => gp::envelope::Payload::Error(gp::Error {
code: 409,
message: "Responses should not be sent as requests".to_string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ mod state_machine_tests {
.max()
.unwrap_or(0);
assert_eq!(
era, 300,
era,
3 * crate::economic::native_reserve::ERA_FAUCET_PAYOUT,
"current_state must reflect the canonical head's balance"
);
assert_eq!(cs.hash, head.root(), "hash is the canonical SMT root");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ const ERA_POLICY_PROTO: [u8; 40] = [
0x03, b'E', b'R', b'A', //
// alias "ERA".
0x00, 0x03, b'E', b'R', b'A', //
// decimals: whole ERA.
0x00, //
// genesis supply: 80,000,000,000 (u128, big-endian; owner, 2026-09-26).
// decimals: two (SoFi Amendment S18, owner 2026-10-01).
0x02, //
// genesis supply: 80,000,000,000.00 ERA, which is 8,000,000,000,000 base
// units (u128, big-endian; owner 2026-09-26, in base units since S18).
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x12, 0xA0, 0x5F, 0x20, 0x00, //
0x00, 0x00, 0x07, 0x46, 0xA5, 0x28, 0x80, 0x00, //
// description: none; icon: none.
0x00, 0x00, 0x00, 0x00, //
// recipient allowlist: none (kind NONE, count 0).
Expand Down Expand Up @@ -84,7 +85,7 @@ mod tests {
);
assert_eq!(
crate::utils::text_id::encode_base32_crockford(&era_policy_commit()),
"JXPMPGJH45HDTE0ARWE2CTB9E9BWTQZ3T78CE5RFF1RXMR9VKK80"
"NNG176RZ6ACTWCDPRNYHXZK2DCZ72SPA9Q6XWGRGQ9JGKZYTESG0"
);
}

Expand All @@ -97,16 +98,16 @@ mod tests {
assert_eq!(decoded.encode_to_vec(), era_policy_bytes());
}

/// Every field of ERA's policy, as SoFi Amendment S11 fixes it.
/// Every field of ERA's policy, as SoFi Amendments S11 and S18 fix it.
#[test]
fn eras_policy_states_what_the_specification_fixes() {
assert_eq!(
era_policy().expect("ERA's policy parses"),
&TokenPolicy {
ticker: "ERA".into(),
alias: "ERA".into(),
decimals: 0,
genesis_supply: 80_000_000_000,
decimals: 2,
genesis_supply: 8_000_000_000_000,
release: Release::Faucet,
description: None,
icon_url: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use crate::types::error::DsmError;
/// conservation guard must be able to validate it. The guard is a pure function
/// over `(operation, deltas)`; a fee it cannot see is a fee it cannot enforce,
/// and a fee that a runtime map could change is not a protocol rule. The SDK's
/// schedule now READS this value, so there is exactly one authority.
pub const TOKEN_CREATION_FEE_ERA: u64 = 10;
/// schedule now READS this value, so there is exactly one authority. In base
/// units: 10.00 ERA at ERA's two decimals (SoFi Amendment S18).
pub const TOKEN_CREATION_FEE_ERA: u64 = 1_000;

/// Display-only ticker resolution for non-builtin (CPTA-anchored) tokens.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@ use crate::types::proto as generated;

type D32 = [u8; 32];

/// The whole distributable ERA supply of one network at genesis. Nothing is
/// minted after it; every unit in circulation was released from it.
pub const ERA_RESERVE_GENESIS_SUPPLY: u64 = 80_000_000_000;
/// The whole distributable ERA supply of one network at genesis, in base
/// units: 80,000,000,000.00 ERA at ERA's two decimals (SoFi Amendment S18).
/// Nothing is minted after it; every unit in circulation was released from it.
pub const ERA_RESERVE_GENESIS_SUPPLY: u64 = 8_000_000_000_000;

/// What one beta faucet claim releases. ERA is whole-unit (`decimals = 0`),
/// so this is literally 100 ERA. The claim names no amount: the beta claim
/// policy fixes it, and the accepting transition refuses any other delta.
pub const ERA_FAUCET_PAYOUT: u64 = 100;
/// What one beta faucet claim releases, in base units: 100.00 ERA (SoFi
/// Amendment S18). The claim names no amount: the beta claim policy fixes it,
/// and the accepting transition refuses any other delta.
pub const ERA_FAUCET_PAYOUT: u64 = 10_000;

/// Matches the proto's `dsm_max_len`; prost does not enforce it, so this
/// module does.
Expand Down Expand Up @@ -849,7 +850,7 @@ mod tests {

#[test]
fn the_envelope_round_trips_and_is_strict() {
let release = signed(&genesis(), 100);
let release = signed(&genesis(), ERA_FAUCET_PAYOUT);
let bytes = release.envelope_bytes.clone();
// Decodable-but-non-canonical: unknown field, silently skipped by
// prost, caught only by the re-encode comparison.
Expand Down Expand Up @@ -1041,7 +1042,7 @@ mod tests {
release_constructible(&r0, &zero),
Err(ReleaseRefusal::ZeroRelease)
);
let (release, pk) = signed_with_key(&r0, 100);
let (release, pk) = signed_with_key(&r0, ERA_FAUCET_PAYOUT);
let r1 = release_constructible(&r0, &release).expect("constructible");
// Every unit that left the reserve is accounted to the recipient the
// body names, and that recipient is the signer.
Expand All @@ -1057,29 +1058,29 @@ mod tests {
fn a_release_must_succeed_exactly_its_parent() {
let r0 = genesis();
let (pk, sk) = keypair();
let mut wrong_root = body(&r0, 100, &pk);
let mut wrong_root = body(&r0, ERA_FAUCET_PAYOUT, &pk);
wrong_root.parent_root = [0xEE; 32];
let wrong_root =
decode_and_verify_release(&sign_release(&wrong_root, &sk).unwrap()).unwrap();
assert_eq!(
release_constructible(&r0, &wrong_root),
Err(ReleaseRefusal::ParentRootMismatch)
);
let mut wrong_gen = body(&r0, 100, &pk);
let mut wrong_gen = body(&r0, ERA_FAUCET_PAYOUT, &pk);
wrong_gen.generation = 2;
let wrong_gen = decode_and_verify_release(&sign_release(&wrong_gen, &sk).unwrap()).unwrap();
assert_eq!(
release_constructible(&r0, &wrong_gen),
Err(ReleaseRefusal::GenerationIsNotSuccessor)
);
let mut other = body(&r0, 100, &pk);
let mut other = body(&r0, ERA_FAUCET_PAYOUT, &pk);
other.reserve_id = era_reserve_id(b"othernet");
let other = decode_and_verify_release(&sign_release(&other, &sk).unwrap()).unwrap();
assert_eq!(
release_constructible(&r0, &other),
Err(ReleaseRefusal::NamesAnotherReserve)
);
let mut foreign = body(&r0, 100, &pk);
let mut foreign = body(&r0, ERA_FAUCET_PAYOUT, &pk);
foreign.storage_set_id = [0x77; 32];
let foreign = decode_and_verify_release(&sign_release(&foreign, &sk).unwrap()).unwrap();
assert_eq!(
Expand All @@ -1097,7 +1098,7 @@ mod tests {
#[test]
fn finality_without_the_deterministic_leader_is_impossible() {
let r0 = genesis();
let release = signed(&r0, 100);
let release = signed(&r0, ERA_FAUCET_PAYOUT);
let x = release.envelope_bytes.clone();
let (at, mut skipped_leader) = successor_cell(&r0);
skipped_leader.write(&x, ROUTE_LEN - 1, &[0]);
Expand Down Expand Up @@ -1130,7 +1131,7 @@ mod tests {
#[test]
fn unrecognized_bytes_never_occupy_the_cell() {
let r0 = genesis();
let release = signed(&r0, 100);
let release = signed(&r0, ERA_FAUCET_PAYOUT);
// Signed, canonical, succeeding R_0 — and releasing more than exists.
let too_much = signed(&r0, ERA_RESERVE_GENESIS_SUPPLY + 1);
let (at, mut cell) = successor_cell(&r0);
Expand All @@ -1153,8 +1154,8 @@ mod tests {
#[test]
fn additional_replicas_do_not_alter_the_winner() {
let r0 = genesis();
let a = signed(&r0, 100);
let b = signed(&r0, 100);
let a = signed(&r0, ERA_FAUCET_PAYOUT);
let b = signed(&r0, ERA_FAUCET_PAYOUT);
let child_a = release_constructible(&r0, &a).unwrap();
let (at, mut cell) = successor_cell(&r0);
cell.write(&a.envelope_bytes, 0, &[]);
Expand Down Expand Up @@ -1183,7 +1184,7 @@ mod tests {
#[test]
fn a_final_release_has_a_completion_proof_that_checks() {
let r0 = genesis();
let release = signed(&r0, 100);
let release = signed(&r0, ERA_FAUCET_PAYOUT);
let (at, mut cell) = successor_cell(&r0);
cell.write(&release.envelope_bytes, 1, &[]);
assert_eq!(successor_completion(&at, &cell.evidence()), Ok(None));
Expand All @@ -1206,7 +1207,7 @@ mod tests {
#[test]
fn the_walk_advances_through_final_releases_and_stops_at_the_head() {
let r0 = genesis();
let rel1 = signed(&r0, 100);
let rel1 = signed(&r0, ERA_FAUCET_PAYOUT);
let r1 = release_constructible(&r0, &rel1).unwrap();
let rel2 = signed(&r1, ERA_FAUCET_PAYOUT);
let r2 = release_constructible(&r1, &rel2).unwrap();
Expand Down Expand Up @@ -1267,7 +1268,7 @@ mod tests {
})
);
assert_eq!(visited, 0, "nothing final was read");
let rel1 = signed(&r0, 100);
let rel1 = signed(&r0, ERA_FAUCET_PAYOUT);
let r1 = release_constructible(&r0, &rel1).unwrap();
let stop = walk_lineage(
r0,
Expand Down
Loading
Loading