# `gno.land/p/moul/x/wesh/v0`
**The publishable half of the Wesh protocol** (weshnet, the network behind
[Berty](https://berty.tech)) as a pure gno library: `Contact`, `WebLink`,
`ParseWebLink`, `RendezvousPoint`, `SeedCommitment`, `BindStatement`,
`DeviceStatement`, `VerifyBind`, `VerifyDevice`, `HMACSHA256`.
```go
import "gno.land/p/moul/x/wesh/v0"
c := wesh.Contact{AccountPK: pk, Seed: seed, DisplayName: "Alice"}
link, _ := c.WebLink() // https://berty.tech/id#contact/<base58>/name=Alice
pt, _ := c.RendezvousPointAt(now, wesh.DefaultRotationInterval)
```
## Why a chain at all
Wesh is off-grid, peer-to-peer and end-to-end encrypted. A public chain is the
opposite in nearly every dimension, so this is deliberately **not** "weshnet on
chain". It carries only the parts that need an authenticated, ordered, publicly
auditable record, the one thing a peer-to-peer network cannot give itself, and
which Wesh is missing in three specific places:
- **Identities do not resolve.** A Berty ID travels out of band as a QR code or
a `https://berty.tech/id#` link, and there is no lookup.
- **Seed resets are silent.** `ContactRequestResetReference` gives the account a
new rendezvous seed, which kills every link ever shared, with no channel to
announce it.
- **Devices can never be revoked.** The protocol documentation says so outright:
the account metadata log is append-only and no authority can void an entry.
## What is in here
| piece | what it is |
|---|---|
| `Contact` | weshnet's `ShareableContact`: account key + public rendezvous seed + display name, with weshnet's own `CheckFormat` length rules |
| `Blob`, `WebLink`, `ParseWebLink` | the Berty link codec, hand-rolled protobuf + base58 |
| `RendezvousPoint`, `RoundPeriod`, `NextPeriod` | weshnet's rotating DHT topic derivation |
| `SeedCommitment`, `OpenCommitment` | publish `H(seed ‖ salt)` instead of the seed |
| `BindStatement`, `DeviceStatement`, `VerifyBind`, `VerifyDevice` | the canonical texts an account signs, and their ed25519 verification |
| `HMACSHA256` | RFC 2104, because gno has `sha256.Sum256` but no `crypto/hmac` |
**The link codec is conformance-tested**, not guessed: `TestBlobEncodingMatches
BertyGoldenVector` reproduces the exact base58 payload from berty's own
`links_test.go`, byte for byte. The rendezvous derivation is pinned against
vectors computed with weshnet's `GenerateRendezvousPointForPeriod`, and the HMAC
against RFC 4231, including case 6, the longer-than-block-size key.
## What is deliberately absent
There is **no type here that can hold a secret**. Group secrets, device chain
keys, message keys and ciphertexts never touch a chain: publishing a group
secret hands the group to everyone, and publishing ciphertext is permanent,
expensive, and leaks the social graph through access patterns.
## The privacy trade-off
Publishing a rendezvous seed is equivalent to printing your Berty QR code on a
billboard: anyone can then derive today's rendezvous point and watch the DHT for
it. That is the right trade only for an identity that *wants* to be found.
`SeedCommitment` is the alternative: the chain attests the binding, the seed
travels out of band, and the rendezvous point stays private.
## Cost
`WebLink` is base58 over a ~70-byte payload, which is big-integer work:
`TestWebLink` reports ~19M gas for one encode, `TestWebLinkRoundTrip` ~61M per
encode-plus-decode. That is fine in a `Render` (a query) and worth avoiding
per-row in a list. Signature verification is a native op and costs far less.
**Live realm:** [`r/moul/x/wesh`](https://github.com/moul/gno-contracts/tree/main/r/moul/x/wesh/v0)
· render it at [`/r/moul/x/wesh/v0`](https://gno.land/r/moul/x/wesh/v0).
<!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) -->
---
Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
**Dependency graph:**

> 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md).
<!-- END GNOCONTRACTS FOOTER -->
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.