Skip to content

feature: IPNS support (registration, tracking, republishing, gateway)#1183

Open
odesenfans wants to merge 18 commits into
mainfrom
ipns-support
Open

feature: IPNS support (registration, tracking, republishing, gateway)#1183
odesenfans wants to merge 18 commits into
mainfrom
ipns-support

Conversation

@odesenfans

Copy link
Copy Markdown
Collaborator

Summary

Adds first-class, paid IPNS name support to Aleph Cloud. A STORE message with the new item_type: ipns registers an IPNS name (item_hash is the base36 k51... name):

  • Publish: the message carries a user-signed IPNS record (ipns_record, base64, 10 KiB cap). The node verifies it against the name via kubo, pins the record's value CID within the paid quota (max_size_mib), stores the registration in the new ipns_records table and injects the record into the DHT. No node ever holds a private key.
  • Update: same message shape with a higher record sequence number. Updates self-order by sequence, so out-of-order processing needs no chain logic (ref is forbidden for IPNS content). The registration keeps exactly one re-pointable pin; replaced CIDs get the existing grace-period treatment and superseded messages stop billing.
  • Track-only: omit ipns_record and the node fetches the current record from the DHT, then proceeds identically (keep-alive for names managed elsewhere).
  • Republish worker: a periodic job (default 4h, ipfs.ipns.* config) re-injects records (kubo DHT records expire within ~24-48h) and re-resolves names to adopt newer records, with per-record failure isolation. Over-quota content keeps the last good CID pinned (status=over_quota); expired records stop republishing but stay pinned (status=expired).
  • API: GET /api/v0/ipns/{name} (registration state, used by clients to bootstrap sequence numbers), GET /api/v0/ipns/{name}/raw (302 to /api/v0/storage/raw/{cid}), GET /api/v0/addresses/{address}/ipns. Registered names only: CCNs are not open IPNS resolvers.
  • Uploads: add_file/add_car accept IPNS STORE metadata; the uploaded (root) CID must match the signed record's value instead of item_hash.
  • Pricing: flat name fee (new CostType.IPNS, covers republish work) plus storage billed on the declared quota, so billing never changes without a message. Defaults live in DEFAULT_PRICE_AGGREGATE under the new ipns product and are tunable via the network pricing aggregate.

Dependencies and rollout

  • Depends on aleph-message branch ipns-support (new ItemType.ipns shape rule + StoreContent fields), consumed as a git dependency in pyproject.toml. To be swapped for a released version once stabilized.
  • Rollout note: nodes running released aleph-message reject IPNS STOREs as malformed (k51 names fail ItemHash validation), a clean failure. The network needs to upgrade before IPNS traffic flows, standard for additive message-type changes.
  • Migration 0060_c7d2e9f4a1b8 creates ipns_records; file_pins gains only a new polymorphic type value.

Test plan

  • aleph-message: 17 new unit tests (shape rule, StoreContent validators); suite at baseline (90 passed)
  • pyaleph: 44 new tests across models, accessors, IpfsService kubo wrappers, pricing, handler (publish/update/track/stale/forget/quota/cost-migration), republish worker, API endpoints, uploads
  • Full suite: 864 passed, 10 skipped; only pre-existing environmental errors (ethereum tests need a local anvil)
  • End-to-end against a live kubo daemon (record signing via SDK, DHT round-trip)

Add IpnsStatus enum, IpnsRecordDb SQLAlchemy model, FilePinType.IPNS
member with IpnsFilePinDb subclass, and the ipfs.ipns config subsection.
…or tests

- Change insert_ipns_file_pin to target concrete IpnsFilePinDb subclass
- Pass FilePinType.IPNS enum member instead of .value for consistency
- Remove redundant type discriminator clause from get_ipns_file_pin
- Add status ChoiceType round-trip assertion in upsert test
- Parameterize _upsert helper with owner to enable multi-owner testing
- Add test_multiple_owners_same_ipns_name to verify two owners can register the same name
…ath coverage

Replace assert with explicit error handling in _calculate_ipns_costs to clearly communicate
quota requirement to callers. Add comment explaining why stream component is unused in STORE
messages. Add ProductPriceType.IPNS to default pricing model test. Add test_ipns_costs_credit_payment
to cover credit payment path and test_product_pricing_parses_fixed_fee to verify fixed fee
parsing from DEFAULT_PRICE_AGGREGATE.
Implement the IPNS registration flow in StoreMessageHandler: fetch the
signed record (or resolve it from the DHT for track-only messages),
verify via kubo, enforce the max_size_mib quota, pin the resolved CID,
store state in ipns_records and maintain exactly one re-pointable
IpnsFilePinDb pin per registration. Stale sequence numbers are safe
no-ops; superseded-message costs are cleaned up on update; forget
tears down the registration and grace-period-pins the old CID.

Also adds delete_ipns_file_pin accessor (needed for clean forget) and
11 focused integration tests covering publish, update, stale sequence,
track-only, DHT failure, invalid record, expired record, over-quota,
forget teardown, forget-superseded no-op, and cost row migration.
Adds IpnsRepublisher that re-injects stored signed records into the
DHT every republish_period_hours (default 4h) and re-resolves each
name to adopt newer records published out-of-band.  Over-quota content
keeps the last good CID pinned and flips status to OVER_QUOTA; expired
records flip to EXPIRED and stop being republished.  Old CIDs are
grace-period-pinned before being dropped.

Wires ipns_republisher_task into commands.py guarded by
config.ipfs.enabled and config.ipfs.ipns.enabled.
The best registration tie-break now sorts by (sequence, owner) for determinism
when multiple registrations have the same sequence. Added test coverage for
the 404 case when resolved_cid is None.
For IPNS STORE messages (item_type=ipns), the item_hash is the IPNS
name, not the content CID. For uploads that include signed IPNS
metadata, verify the uploaded CID against the value inside the signed
IPNS record (record.value_cid) instead of message_content.item_hash.

Add _verify_ipns_record_and_get_cid helper that decodes and verifies
the embedded record via IpfsService.verify_ipns_record, and
_check_ipns_upload that asserts the uploaded CID matches. Both
ipfs_add_file and ipfs_add_car are updated to use these helpers when
item_type is ipns; the existing ipfs item_type path is unchanged.
…erage

Add check for None ipfs_service in _verify_ipns_record_and_get_cid to prevent
NoneType errors when IPFS is disabled. Extend upload endpoint docstrings and
error messages to document support for item_type=ipns. Add comprehensive test
coverage for invalid IPNS records with grace period verification.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant