You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
key-wallet: platform node id uses HASH160 but the canonical value is the Tenderdash node ID (SHA256[0..20]) — platform-node matching can never hit on-chain registrations #883
key-wallet computes the masternode platform node id as HASH160(ed25519_pubkey) (RIPEMD160∘SHA256), but the canonical value — what Tenderdash announces on the platform P2P network and what ProRegTx builders write on-chain — is the Tenderdash/CometBFT node ID: the first 20 bytes of a single SHA256 of the Ed25519 public key. The result: key-wallet's derived node ids never match real on-chain platform_node_id values, so provider-key matching (#863/#864) and any wallet UI can never associate a wallet's platform-node key with its own evonode registration.
Follow-up in the #878/#879/#881 series: with #879/#881 in place, operator BLS keys now match DashSync end-to-end (user-verified with a shared mnemonic); the platform node id is the remaining divergence.
Evidence
DashSync builds ProRegTx with truncated SHA256 — dashsync-iOS, DSLocalMasternode.m:458-459:
UInt256 platformNodeHash = [DSKeyManager publicKeyData:platformNodeKey].SHA256; // single SHA-256
UInt160 platformNodeID = *(UInt160 *)&platformNodeHash; // first 20 bytes
(-SHA256 is a single SHA-256, NSData+Dash.m:1115-1120; contrast the ECDSA owner key at :471 which uses .hash160.) This matches the CometBFT/Tenderdash node-ID convention — node ID = SHA256(pubkey)[0..20] — which is what dashmate derives from node_key.json and what the evonode actually advertises, i.e. the value the on-chain field must carry for platform P2P to work.
key-wallet/src/account/eddsa_account.rs:350-356 (derive_address_at): P2PKH pseudo-address from hash160
key-wallet/src/transaction_checking/account_checker.rs:1034-1048: ProRegTx matching compares reg.platform_node_id against the hash160-derived pool entries — so a real registration (SHA256[:20]) can never match
dash/src/blockdata/transaction/special_transaction/provider_registration.rs:111: the field is typed platform_node_id: Option<PubkeyHash> — wire-compatible (20 bytes) but semantically it is a Tenderdash node id, not a public key hash
SLIP-0010 derivation itself appears aligned: both sides use m/9'/coin'/3'/4'/index' (all hardened) with standard SLIP-0010; BLS parity post-#879 confirms the seed/path plumbing. Caveat: DashSharedCore ships as a compiled binary locally, and the wallet UIs display keys in different encodings (base64 vs hex), so raw-pubkey equality is assumed rather than byte-verified — if a residual key-level divergence exists it would be inside DashSharedCore's SLIP-0010 primitive, but the hashing divergence documented above is real and sufficient to break matching regardless.
Proposed fix
Compute the platform node id as SHA256(ed25519_pubkey)[0..20] wherever key-wallet derives or matches it (identifier() for the platform-node context, derive_address_at pseudo-addressing for the ProviderPlatformKeys pool, and the account_checker ProRegTx comparison).
Consider a dedicated PlatformNodeId newtype instead of PubkeyHash on ProviderRegistrationPayload to prevent the conventions from being conflated again (wire format unchanged).
Pin with a test vector: known seed → ed25519 pubkey → node id, cross-checked against a dashmate/Tenderdash-generated node ID for the same key.
Activity
fix(key-wallet): platform node id is the Tenderdash node ID (SHA256[0…
feat(dash): dedicated PlatformNodeId newtype for platform_node_id fie…