adopt

package
v1.36.178 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: BSD-3-Clause Imports: 3 Imported by: 0

Documentation

Overview

Package adopt is the register of networks Lux did not create.

A network normally reaches the P-chain by being made: a chain is created, a validator set is assigned, it produces blocks. That path assumes the network does not exist yet. Ethereum, Bitcoin, Solana and Base all exist, and none of it is Lux's to create or validate.

Adoption records a BELIEF about such a network — that it is the one named, reachable where stated, and that messages attributed to it can be trusted on a stated basis. It confers nothing on the adopted network, which has agreed to nothing, and it grants Lux no authority over it.

The register is here rather than in a contract because every subsystem needs to read it before acting: the bridge before releasing, the oracle before attesting, the custody chain before signing. A P-chain record is the one thing all of them can already see.

See LP-1021.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoChainID     = errors.New("adopt: chain id required")
	ErrNoIdentity    = errors.New("adopt: identity commitment required")
	ErrBadAnchor     = errors.New("adopt: unknown anchor")
	ErrBadHolding    = errors.New("adopt: unknown holding")
	ErrNoEndpoints   = errors.New("adopt: at least one endpoint required")
	ErrSelfParent    = errors.New("adopt: a network cannot take security from itself")
	ErrCustodyUnheld = errors.New("adopt: a declared anchor may not carry custody")
	ErrNoCustody     = errors.New("adopt: an anchor that holds value needs a custody key")
)
View Source
var (
	ErrAlreadyAdopted = errors.New("adopt: already adopted")
	ErrNotAdopted     = errors.New("adopt: not adopted")
	ErrNoParent       = errors.New("adopt: the network it takes security from is not adopted")
	ErrParentHeld     = errors.New("adopt: a network still takes security from this one")
	ErrWeakerAnchor   = errors.New("adopt: weakening an anchor is a separate act")
)

Functions

This section is empty.

Types

type Anchor

type Anchor uint8

Anchor is the basis for believing a message attributed to an adopted network. It is the whole security boundary: everything downstream inherits exactly this and nothing more.

const (
	// Declared: governance asserted the network is what it says it is.
	// Proves the estate agreed and nothing else. Enough to list a network,
	// open markets against it and issue assets — never enough to hold value,
	// because signing a transfer on a chain nobody has verified is custody
	// without evidence.
	Declared Anchor = iota + 1

	// Attested: t+1 of the validator set independently observed the network
	// and threshold-signed what they saw. Proves they read the same thing;
	// leaves open whether they read it correctly, which is why finality depth
	// belongs in the record. This is the level at which value may cross.
	Attested

	// Proven: the network's own consensus is verified — a light client, a sync
	// committee signature, a validity proof. Proves the message is in a block
	// the network's own validators finalised.
	Proven
)

func (Anchor) Custodial

func (a Anchor) Custodial() bool

Custodial reports whether value may be held under this anchor.

The line sits between Declared and Attested and is the reason adoption can be permissionless: paying a fee buys a record, and a record is not a trust decision. Attestation cannot be bought, because what it requires is the committee actually observing the network.

func (Anchor) String

func (a Anchor) String() string

type Holding

type Holding uint8

Holding is how value is held on the adopted network.

const (
	// Gateway: a contract or program holds the position and a release is a
	// call to it. Every EVM, Solana, TON.
	Gateway Holding = iota + 1

	// Address: there is nowhere to put a contract, so the custody address IS
	// the gateway — a deposit is the lock and a signed spend is the release.
	// Bitcoin. Everything a contract would have enforced moves into the
	// attestation, which makes the anchor matter more here, not less.
	Address
)

func (Holding) String

func (h Holding) String() string

type Record

type Record struct {
	// ChainID is the network's own chain id — 1 for Ethereum, 8453 for Base.
	ChainID uint64

	// Identity commits to WHICH chain bears that id: a genesis hash, or an
	// equivalent. A chain id alone is not an identity. Ids collide across
	// testnets, and a fork inherits the id of the chain it left, so without
	// this a split is invisible to the register.
	Identity ids.ID

	// Parent is the adopted network this one takes its security from, or the
	// empty ID when the network is sovereign. Base names Ethereum; Ethereum
	// names nothing.
	Parent ids.ID

	// Anchor is why Lux believes messages attributed to this network.
	Anchor Anchor

	// Holding is how value is held there.
	Holding Holding

	// Custody is the M-Chain key that signs for this network. Empty while the
	// anchor is Declared, because a declared anchor may not hold value.
	Custody string

	// Endpoints is where the network is reachable.
	Endpoints []string

	// Depth is how many blocks of the adopted network must pass before its
	// state is attested. A committee that reads a reorged chain attests a
	// reorged chain, so this is the register's own statement of how much
	// reorg it is willing to tolerate.
	Depth uint64
}

Record is one adopted network.

func (Record) Key

func (r Record) Key() ids.ID

Key identifies a record. The identity commitment rather than the chain id, so a fork does not silently overwrite the chain it left.

func (Record) Sovereign

func (r Record) Sovereign() bool

Sovereign reports whether the network's security is its own.

func (Record) Valid

func (r Record) Valid() error

Valid reports whether a record is well formed on its own terms. It says nothing about the register it is going into — see Registry.Adopt for the rules that need to see other records.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry holds the adopted networks.

func NewRegistry

func NewRegistry() *Registry

func (*Registry) Adopt

func (g *Registry) Adopt(r Record) error

Adopt records a network.

The rule with teeth: a network that takes its security from another may not be adopted before that other one. It is not bookkeeping. A Base state root is meaningful because it is posted to Ethereum and challengeable there — so adopting Base alone records a belief whose entire basis is a chain the register has never heard of, and the anchor cites a proof nobody can check. Ethereum first, then Base against it.

func (*Registry) Get

func (g *Registry) Get(id ids.ID) (Record, bool)

Get returns a record and whether it is there.

func (*Registry) Len

func (g *Registry) Len() int

Len is how many networks are adopted.

func (*Registry) MayHold

func (g *Registry) MayHold(id ids.ID) bool

MayHold reports whether value may cross to this network — the single question a bridge asks before releasing.

Unadopted answers no. That is the difference this register exists to make: before it, a bridge trusted a config file and nothing on chain said the estate had ever sanctioned it.

func (*Registry) Release

func (g *Registry) Release(id ids.ID) error

Release ends an adoption.

Refused while another adopted network takes its security from this one: the survivor's anchor is a claim about the released chain, and releasing the chain it cites makes that claim unreadable. This is the adoption ordering running backwards, and it is the same rule.

Release is not a delete of history. Positions attested before release remain attested, because they were: what release ends is new crossings, not the evidence for old ones.

func (*Registry) Revise

func (g *Registry) Revise(r Record) error

Revise changes a record in place.

An anchor may be strengthened freely: it costs nobody anything and every consumer is relying on less than it now gets. Weakening one is refused here and needs its own act, because a bridge, an indexer or an interface deciding what to show a user all read the anchor to know what a message is worth — and weakening it changes what every one of them is trusting without any of them being asked.

A record's identity and its parent do not change. A network that forks is a different network and gets its own record; a network that changes where its security comes from has become something else.

func (*Registry) Weaken

func (g *Registry) Weaken(id ids.ID, to Anchor) error

Weaken lowers an anchor. Separate from Revise so that it cannot happen by accident, and so the act is legible in a log as what it is.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL