Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
24 changes: 12 additions & 12 deletions Cargo.lock

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

16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ members = [
]

[workspace.dependencies]
dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "337f6ccc7f45a5f7a50abf0d6fecb1ef0b786e7b" }
dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a407883fc49a08cdb3b72845fdfc77983af92b" }

tokio-metrics = "0.5"

Expand Down
25 changes: 22 additions & 3 deletions packages/rs-platform-wallet-ffi/src/provider_key_at_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ pub const PROVIDER_KEY_KIND_PLATFORM_NODE: u8 = 11;
pub struct ProviderKeyAtIndexFFI {
/// The key index that was derived (`#0..`).
pub index: u32,
/// Null-terminated lowercase hex of the raw curve public key — 96
/// hex chars for a BLS-48 operator key, 64 for an Ed25519-32
/// platform-node key. Null on the pre-cleared / freed state.
/// Null-terminated lowercase hex of the raw curve public key in the
/// MODERN (IETF) serialization — 96 hex chars for a BLS-48 operator
/// key, 64 for an Ed25519-32 platform-node key. Null on the
/// pre-cleared / freed state.
pub public_key_hex: *mut c_char,
/// Null-terminated lowercase hex of the SAME BLS G1 point in the Dash
/// LEGACY serialization (96 chars). Non-null only for operator (BLS)
/// keys; null for Ed25519 platform-node keys (no legacy variant) and
/// on the empty state.
pub legacy_public_key_hex: *mut c_char,
/// Null-terminated lowercase hex of the 20-byte platform node id
/// (40 chars) — `hash160` of the Ed25519 public key. Null for
/// operator keys (no node id) and on the empty state.
Expand All @@ -85,6 +91,7 @@ impl ProviderKeyAtIndexFFI {
Self {
index: 0,
public_key_hex: std::ptr::null_mut(),
legacy_public_key_hex: std::ptr::null_mut(),
node_id_hex: std::ptr::null_mut(),
private_key_hex: std::ptr::null_mut(),
}
Expand Down Expand Up @@ -228,11 +235,18 @@ pub unsafe extern "C" fn platform_wallet_provider_key_at_index(
let ProviderDerivedKey {
index,
public_key_bytes,
legacy_public_key_bytes,
node_id,
private_key,
} = derived;

let public_key_hex = unwrap_result_or_return!(CString::new(hex::encode(public_key_bytes)));
// Legacy BLS form (operator keys only; `None` for Ed25519). Public
// material, so a plain `CString::new` is fine.
let legacy_public_key_hex = match legacy_public_key_bytes {
Some(bytes) => unwrap_result_or_return!(CString::new(hex::encode(bytes))).into_raw(),
None => std::ptr::null_mut(),
};
let node_id_hex = match node_id {
Some(id) => unwrap_result_or_return!(CString::new(hex::encode(id))).into_raw(),
None => std::ptr::null_mut(),
Expand All @@ -252,6 +266,7 @@ pub unsafe extern "C" fn platform_wallet_provider_key_at_index(
*out = ProviderKeyAtIndexFFI {
index,
public_key_hex: public_key_hex.into_raw(),
legacy_public_key_hex,
node_id_hex,
private_key_hex,
};
Expand Down Expand Up @@ -281,6 +296,10 @@ pub unsafe extern "C" fn platform_wallet_provider_key_at_index_free(
let _ = unsafe { CString::from_raw(out.public_key_hex) };
out.public_key_hex = std::ptr::null_mut();
}
if !out.legacy_public_key_hex.is_null() {
let _ = unsafe { CString::from_raw(out.legacy_public_key_hex) };
out.legacy_public_key_hex = std::ptr::null_mut();
}
if !out.node_id_hex.is_null() {
let _ = unsafe { CString::from_raw(out.node_id_hex) };
out.node_id_hex = std::ptr::null_mut();
Expand Down
43 changes: 30 additions & 13 deletions packages/rs-platform-wallet/src/wallet/provider_key_at_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,20 @@ impl ProviderKeyKind {
pub struct ProviderDerivedKey {
/// The key index within the provider pool (`#0..`).
pub index: u32,
/// Raw curve public key bytes: 48 for a BLS operator key (this is
/// exactly the bytes a ProRegTx `operator_public_key` field
/// carries), 32 for an Ed25519 platform-node key.
/// Raw curve public key bytes in the MODERN (IETF) serialization: 48
/// for a BLS operator key (this is exactly the bytes a ProRegTx
/// `operator_public_key` field carries), 32 for an Ed25519
/// platform-node key.
pub public_key_bytes: Vec<u8>,
/// The SAME BLS G1 point serialized in the Dash **legacy** scheme (48
/// bytes; same point, legacy flag bits in `byte[0]`) — the form
/// dashbls/DashSync use across the BLS HD chain. `Some` only for
/// operator (BLS) keys; `None` for Ed25519 platform-node keys, which
/// have no legacy variant. Produced Rust-side via
/// `ExtendedBLSPubKey::to_bytes_legacy` / `ExtendedBLSPrivKey::
/// public_key_bytes_legacy` (key-wallet #879) — never transformed in
/// Swift.
pub legacy_public_key_bytes: Option<Vec<u8>>,
/// The 20-byte platform node id — `hash160` of the Ed25519 public
/// key, the value a ProRegTx `platform_node_id` field carries and
/// the [`Payload::PubkeyHash`](dashcore::address::Payload) the pool
Expand Down Expand Up @@ -327,6 +337,10 @@ impl PlatformWallet {
))
})?;
let public_key_bytes = derived.public_key_bytes().to_vec();
// Same G1 point, Dash legacy serialization (key-wallet
// #879) — for the "BLS Public Key (Legacy)" display row.
let legacy_public_key_bytes =
Some(derived.public_key_bytes_legacy().to_vec());

// The private-path public key must equal the
// watch-only `ckd_pub` derivation the pool /
Expand All @@ -348,27 +362,28 @@ impl PlatformWallet {
Ok(ProviderDerivedKey {
index,
public_key_bytes,
legacy_public_key_bytes,
node_id: None,
private_key,
})
}
// Public-only: non-hardened `ckd_pub` off the account
// xpub — no seed / resolver needed for BLS.
None => {
let public_key_bytes = account
.bls_public_key
.derive_pub(child)
.map_err(|e| {
let derived_pub =
account.bls_public_key.derive_pub(child).map_err(|e| {
PlatformWalletError::KeyDerivation(format!(
"failed to derive BLS operator public key at index \
{index}: {e}"
))
})?
.to_bytes()
.to_vec();
"failed to derive BLS operator public key at index {index}: {e}"
))
})?;
// Serialize the same G1 point both ways: modern/IETF
// and Dash legacy (key-wallet #879).
let public_key_bytes = derived_pub.to_bytes().to_vec();
let legacy_public_key_bytes = Some(derived_pub.to_bytes_legacy().to_vec());
Ok(ProviderDerivedKey {
index,
public_key_bytes,
legacy_public_key_bytes,
node_id: None,
private_key: None,
})
Expand Down Expand Up @@ -448,6 +463,8 @@ impl PlatformWallet {
Ok(ProviderDerivedKey {
index,
public_key_bytes,
// Ed25519 platform-node keys have no BLS legacy variant.
legacy_public_key_bytes: None,
node_id: Some(node_id),
private_key,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -939,10 +939,16 @@ extension ManagedPlatformWallet {
public struct ProviderDerivedKey: Sendable {
/// The key index that was derived (`#0..`).
public let index: UInt32
/// Lowercase hex of the raw curve public key — 96 chars for a
/// BLS-48 operator key (the bytes a ProRegTx operator field
/// carries), 64 for an Ed25519-32 platform-node key.
/// Lowercase hex of the raw curve public key in MODERN (IETF)
/// serialization — 96 chars for a BLS-48 operator key (the bytes a
/// ProRegTx operator field carries), 64 for an Ed25519-32
/// platform-node key.
public let publicKeyHex: String
/// Lowercase hex of the SAME BLS G1 point in the Dash LEGACY
/// serialization (96 chars). `nil` for Ed25519 platform-node keys
/// (no legacy variant). Serialized on the Rust side — never
/// transformed in Swift.
public let legacyPublicKeyHex: String?
/// Lowercase hex of the 20-byte platform node id (`hash160` of
/// the Ed25519 public key, the ProRegTx `platform_node_id`).
/// `nil` for operator keys, which have no node id.
Expand All @@ -960,11 +966,13 @@ extension ManagedPlatformWallet {
public init(
index: UInt32,
publicKeyHex: String,
legacyPublicKeyHex: String?,
nodeIdHex: String?,
privateKeyHex: String?
) {
self.index = index
self.publicKeyHex = publicKeyHex
self.legacyPublicKeyHex = legacyPublicKeyHex
self.nodeIdHex = nodeIdHex
self.privateKeyHex = privateKeyHex
}
Expand Down Expand Up @@ -1024,11 +1032,13 @@ extension ManagedPlatformWallet {
try result.check()

let publicKeyHex = out.public_key_hex.map { String(cString: $0) } ?? ""
let legacyPublicKeyHex = out.legacy_public_key_hex.map { String(cString: $0) }
let nodeIdHex = out.node_id_hex.map { String(cString: $0) }
let privateKeyHex = out.private_key_hex.map { String(cString: $0) }
return ProviderDerivedKey(
index: out.index,
publicKeyHex: publicKeyHex,
legacyPublicKeyHex: legacyPublicKeyHex,
nodeIdHex: nodeIdHex,
privateKeyHex: privateKeyHex
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,8 @@ struct AccountDetailView: View {
ManagedPlatformWallet.ProviderDerivedKey(
index: key.index,
publicKeyHex: hexString(key.publicKey),
// Platform-node keys are Ed25519 — no legacy BLS form.
legacyPublicKeyHex: nil,
nodeIdHex: hexString(key.nodeId),
privateKeyHex: nil
)
Expand Down Expand Up @@ -844,6 +846,18 @@ struct AccountDetailView: View {
copyKey: "\(key.index)-pub"
)

// The same BLS G1 point in Dash's legacy serialization, shown
// only for operator (BLS) keys. Ed25519 platform-node keys have
// no legacy form, so `legacyPublicKeyHex` is `nil` there and the
// row is skipped. Rust emits both encodings — never derived here.
if let legacy = key.legacyPublicKeyHex {
derivedValueRow(
label: "BLS Public Key (Legacy)",
value: legacy,
copyKey: "\(key.index)-pub-legacy"
)
}

if let nodeId = key.nodeIdHex {
derivedValueRow(
label: "Platform Node ID",
Expand Down
Loading