Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Pointer ownership transfer (ADR-0018 in `ant-node`). `ant pointer transfer --key <FILE>
<RECIPIENT>` signs the pointer's final state, at counter `u64::MAX`, pointing at the new
owner's pointer: readers of the address are redirected there by every node that holds it, the
address stays the same, and no node that holds it gives it up, because a final state is
replaced by nothing. It is refused before paying if any peer of the close group holds a final
state for the pointer, if not every peer answers, or if the recipient does not exist or leads
back. `ant pointer finality <ADDRESS>` asks the whole close group whether a pointer is `open`,
`settling`, `unconfirmed` (final on a majority, but not every peer answered), `final` or
`forked`, which is what a recipient checks before relying on a transfer, and `ant pointer controller <ADDRESS>` follows transfers to the pointer that now
decides. In `ant-core`: `Client::pointer_transfer`, `pointer_sign_transfer`,
`pointer_finality` and `pointer_controller`, and the new `Error::PointerFinal` and
`Error::PointerForked`. In the browser: `transferPointer` and `pointerFinality`.

- `ant` is distributed on npm as `@withautonomi/ant`, so `npm install -g @withautonomi/ant`
works in agent sandboxes and CI runners that allow package-manager traffic but block direct
binary downloads (V2-1152). Packaging only: the published packages carry the same signed
Expand All @@ -27,6 +40,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
run.

### Changed
- A pointer read that meets a final state returns the final state a majority of the close group
holds, rather than the merge winner, and asks the whole group until one is found. Two
different final states are a fork only the owner can make, by racing them to different nodes;
with no majority on either, the read fails with `Error::PointerForked` instead of guessing.
Updating a final pointer is refused with `Error::PointerFinal`, before anything is paid.
- `ant update` no longer replaces the binary when `ant` was installed by a package manager. It
still reports whether a newer version is available, then prints the command that will install
it (`npm update -g @withautonomi/ant`). Self-replacing an npm-managed binary left npm's
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ ant-core/src/
│ ├── payment.rs # pay_for_storage, approve_token_spend
│ ├── quote.rs # get_store_quotes from network peers
│ ├── merkle.rs # Merkle batch payment (PaymentMode enum)
│ ├── pointer.rs # pointer_create/update/get/resolve (ADR-0016)
│ ├── pointer.rs # pointer_create/update/get/resolve (ADR-0016), transfer/finality (ADR-0018)
│ └── cache.rs # In-memory LRU chunk cache
│ └── manifest/ # File manifests and ant:// links (ADR-0006)
│ ├── mod.rs # Manifest, ManifestEntry, ContentRef, encode/decode, limits
Expand Down Expand Up @@ -120,7 +120,7 @@ ant-cli/src/
├── data/
│ ├── file.rs # ant file upload/download
│ ├── chunk.rs # ant chunk put/get
│ ├── pointer.rs # ant pointer keygen/address/create/update/get/resolve
│ ├── pointer.rs # ant pointer keygen/address/create/update/get/resolve/transfer/finality/controller
│ ├── manifest.rs # ant manifest create/list/show/link/export/download
│ └── wallet.rs # ant wallet address/balance
└── node/
Expand Down
47 changes: 35 additions & 12 deletions Cargo.lock

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

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@
members = ["ant-core", "ant-cli"]
resolver = "2"

[patch.crates-io]
# The published ant-protocol 4.0.0 has pointers (ADR-0016) but not the final
# state that ownership transfer relies on (ADR-0018 in ant-node). Pin the
# companion revision until a release includes it. Versions are bumped at
# release; this immutable revision remains 4.0.0.
ant-protocol = { git = "https://github.com/WithAutonomi/ant-protocol", rev = "718f60682bb3704b68fbba0bea34f2a0416fa876" }
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ corroboration and write quorum, and pay each state through the same wallet
callback file uploads take. The owner key is passed as its 32-byte seed. Only
nodes that advertise `pointer_protocol` are asked. A write can hand the paid
record and proof to an `onPaid` callback; `storePaidPointer` stores them later
without paying again.
without paying again. `transferPointer` hands a pointer over for good and
`pointerFinality` asks the whole close group whether it is final (see
`ant pointer transfer` below).

Browser protocol v5 and browser manifest v6 advertise only the payment chain ID
and token/vault addresses. RPC providers belong to the application or wallet;
Expand Down Expand Up @@ -309,6 +311,11 @@ owner key is kept as a 32-byte seed in a file only its owner can read (`0600`
on Unix; on Windows it takes its directory's permissions, so keep it in your
user profile). Losing it means the pointer can never be updated again.

The key cannot change hands, but the pointer can: `ant pointer transfer` signs
its final state, pointing at a pointer the new owner holds the key to. Readers
of the address are redirected there, the address stays the same, and the
former owner's key can change nothing any more (ADR-0018 in `ant-node`).

#### `ant pointer keygen --output <FILE>`

Create a new owner key and print the address of the pointer it controls. Never
Expand Down Expand Up @@ -351,6 +358,45 @@ state_id: 5e7d...

Follow a chain of pointers to the target at its end.

#### `ant pointer transfer --key <FILE> <RECIPIENT>`

Hand the pointer over for good to the pointer at `RECIPIENT` (hex), which the
new owner creates first, with a fresh key for each pointer they receive.
Requires `SECRET_KEY` to pay for the final state. Refused before paying if any
peer of the close group holds a final state for the pointer, if not every peer
of the group answers, or if `RECIPIENT` does not exist or leads back to this
pointer. Irreversible once stored. Prints the stored state and the result of
`finality`; a failed `finality` check after the write does not mean the
transfer failed.

#### `ant pointer finality <ADDRESS>`

Ask every peer of the close group whether a pointer is final, and on what:

- `open` — no peer that answered holds a final state; its owner can still
move it. Check `answered`: a peer that did not answer could hold one.
- `settling` — one final state, not yet on a majority of the group.
- `unconfirmed` — one final state on a majority, but not every peer answered,
so a rival could be unseen. Ask again.
- `final` — one final state, held by a majority, every peer answered and none
holds a rival. The only status to rely on before treating a transfer as
done.
- `forked` — its owner signed more than one final state. Reads return the one a
majority holds, or fail if none does.

```
$ ant pointer finality 9f3c...
address: 9f3c...
answered: 7 of 7
status: final
state: pointer 4b1e... (state 77a0..., held by 7 of 7)
```

#### `ant pointer controller <ADDRESS>`

Follow a pointer's transfers to the pointer whose owner now decides what it
resolves to.

### `ant wallet` — Wallet Operations

Inspect the EVM wallet derived from `SECRET_KEY`.
Expand Down
Loading
Loading