package mobile import ( "encoding/hex" "testing" ) // TestDeriveParityWithWeb pins the Go wallet derivation to the TypeScript one // (web/src/wallet/derive.ts). The canonical BIP39 test mnemonic must derive to this // exact Ed25519 sign_pub — the same value the uniweb client showed for this phrase. // If this fails, web and mobile would derive different identities from the same seed // and the "same account on both devices" guarantee breaks. func TestDeriveParityWithWeb(t *testing.T) { const mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" const wantSignPub = "34302746268e7370d35940e1bcef8c0b1c13a857ea6209e6ecc6e9b3af06b3c8" id, err := deriveIdentity(mnemonic) if err != nil { t.Fatalf("deriveIdentity: %v", err) } if got := hex.EncodeToString(id.SignPub); got != wantSignPub { t.Fatalf("sign_pub mismatch:\n got %s\n want %s", got, wantSignPub) } if len(id.SignPriv) != 64 || len(id.KexPub) != 32 || len(id.KexPriv) != 32 { t.Fatalf("bad key lengths: signPriv=%d kexPub=%d kexPriv=%d", len(id.SignPriv), len(id.KexPub), len(id.KexPriv)) } // sign_priv is Go's ed25519 layout: seed || pub, so its tail must equal sign_pub. if got := hex.EncodeToString(id.SignPriv[32:]); got != wantSignPub { t.Fatalf("sign_priv tail != sign_pub:\n got %s\n want %s", got, wantSignPub) } } // TestMnemonicRoundTrip checks a freshly generated phrase validates and derives. func TestMnemonicRoundTrip(t *testing.T) { m, err := NewMnemonic() if err != nil { t.Fatalf("NewMnemonic: %v", err) } if !ValidateMnemonic(m) { t.Fatalf("generated mnemonic failed validation: %q", m) } if _, err := deriveIdentity(m); err != nil { t.Fatalf("deriveIdentity(fresh): %v", err) } if ValidateMnemonic("not a real mnemonic at all please") { t.Fatal("garbage phrase validated as a mnemonic") } }