VeilNet

Taints

Taints divide a realm into compartments, so you decide which anchors can exchange data with each other.

The Containment Rule

A taint is a label for a compartment, such as prod, lab or a generated string. Taints segment traffic inside a realm, much as VLAN tags or security groups do.

Two anchors in a realm can exchange data only if one of them carries every taint that the other carries. An anchor with fewer taints is more general. For example:

AnchorTaints
Gateway Cblue
Client Ablue, purple
Client Bblue, red

A and C exchange data, and so do B and C, because each client carries every taint that C carries. A and B do not, because each carries a taint that the other lacks.

A rule based only on a shared label could not separate A and B, because both clients share blue. Containment keeps them apart.

Fig. 01 — The containment ruleTry it
A{x}B{x, y}C{x, z}D{x, y}
Start from

The hub carries only the label that every spoke has, so it reaches them all. Spokes with different second labels cannot reach each other.

Taints each machine carries
A
{x}
B
{x, y}
C
{x, z}
D
{x, y}
Which pairs exchange data
  • A ↔ ByesA's set is contained in B's
  • C ↔ Dnothey share {x}, but neither set contains the other
  • A ↔ CyesA's set is contained in C's
  • B ↔ Dyesboth carry the same set
  • A ↔ DyesA's set is contained in D's
  • B ↔ Cnothey share {x}, but neither set contains the other

Taints control data and nothing else. Machines in different compartments still connect, find each other, relay for each other and receive the realm's orders and knowledge, but they cannot exchange data. A real anchor carries up to 32 taints, each granted by its credential.

In practice, the rule means the following:

  • Fewer taints reach more anchors. An anchor with only the common label exchanges data with every client that carries it. Choose the common label carefully, because it decides what a gateway can reach.
  • Give each client a label that nobody can guess. Give every client the common label and a label of its own, such as a UUID. Each client then reaches the gateway but no other client.
  • Having no taints is not a wildcard. An anchor with no taints is in the realm's default compartment, which no named taint contains. It therefore reaches no tainted anchor. If you start using taints in a realm, give every anchor in it a taint.
  • An unknown set is refused. An anchor sends no data to a peer whose taints it does not know yet.

Granting Taints

The root key that admits an anchor assigns its taints. The anchor's credential records them, signed with the rest of the credential. The anchor must start with exactly those taints, or it is refused with REASON_CRED_TAINTS. Every peer checks an anchor's taints against its credential, and a renewal that grants different taints is refused.

A member therefore cannot put itself in a compartment. Taints are as strong a boundary as the credential itself, against a hostile member as well as an outsider.

Taint names follow these rules:

  • A name is 1 to 64 bytes of UTF-8, in any script, with no whitespace and no non-printing characters. An invalid name is refused, not cleaned up, so prod and prod can never become two compartments that nobody can tell apart.
  • A name cannot contain @ or +. These characters bind a served network to taints.
  • An anchor carries at most 32 taints.

What Taints Control

Taints control data between peers, and nothing else. Two anchors in different compartments still:

  • connect
  • bootstrap from each other
  • gossip
  • relay for each other
  • answer each other's telemetry
  • receive the realm's orders and knowledge

An anchor often relays traffic for compartments that it cannot exchange data with, in the same way that a realm above relays for a realm below.

Fig. 02 — Taints gate data, and nothing else
A · {blue, purple}B · {blue, red}CONNECTBOOTSTRAP FROM EACH OTHERGOSSIPRELAY FOR EACH OTHERORDERS AND KNOWLEDGEEXCHANGE DATANEITHER SET CONTAINS THE OTHER

A and B share blue, but each carries a taint that the other lacks, so neither set contains the other. They still connect, find each other, gossip, relay for each other and receive the realm's orders and knowledge. Only data between them is refused.

Both ends of a session check taints. If your machine may not exchange data with an anchor, that anchor has no overlay address on your machine, so it appears absent rather than unreachable.

Data must pass both the realm check and the taint check. The two are independent.

Moving a Running Member

A holder of the taint power can move another member to different taints while it runs. To do this, it sends the member a Taints order.

The member saves its new taints, switches to them at once and publishes a record of the move in the realm's knowledge. Every member checks the record and holds the moved member to its new taints.

A peer can learn that a member has moved before it holds the record. Until the record arrives, the peer refuses data with that member in both directions. When the record arrives, the peer checks the member again at once. Data resumes if one set contains the other. If not, any session that is carrying data ends at its next frame.

Fig. 03 — A member moved while it runs
HOLDER OF taintMEMBERPEERTAINTS ORDERTHE NEXT GENERATIONWRITES IT DOWN,MOVES AT ONCECLAIM: NEW GENERATIONNO RECORD HELD YETDATA REFUSED BOTH WAYSTAINT RECORD,SPREADINGRECORD LANDS:CHECKED AGAINIF ONE SET CONTAINS THE OTHER, DATA RESUMESIF NOT, THE NEXT FRAME ON A SESSION CUTS IT

The peer can learn that the member was moved before it learns where to. Until it holds the taint record, it refuses data with the member in both directions. The record arrives as it spreads through the realm, or when two anchors compare what they hold on connecting. The peer then checks the member again at once.

  • The member keeps its new taints across restarts. Its credential still holds the set it was issued with.
  • A member started without a state directory refuses to be moved, with ErrOrderNoDir, because it would forget the move at its next start.
  • If two holders move one member at the same time, one move wins, and the other holder receives ErrOrderGeneration.

On a sovereign network, the guardian moves members. Its root node in the member's realm is lent taint for that one action. See Holding Powers.

Binding Served Networks

A subnet router offers its networks to every peer that may exchange data with it. To offer one network to fewer peers, bind it to some of the router's own taints with @ in its --subnet value. Only peers whose taints are comparable with the binding can then reach that network. Two sets are comparable when one contains the other. Use + to join two of the router's taints in one binding.

For example, --subnet lab0@lab offers lab0 only to peers comparable with {lab}:

A router in {prod, lab}, offering lab0 bound to lab, and lab1 unbound
PeerReaches the routerlab0, bound to {lab}
{lab}YesYes: it reaches lab0
{prod}YesNo, but it reaches lab1
{prod, lab}YesYes

The router enforces the binding too. It drops traffic for a bound network from a peer outside the binding, with the drop reason not-bound. If the router is moved out of a taint that one of its networks is bound to, it stops offering that network until it is moved back, and raises a subnets-withheld event.

On a peer, run sudo conflux anchorctl routes to see which networks the peer accepted, which it refused and why. See Subnet Routers and Exits.

Taint Names

A taint name never crosses the network. On the wire, a taint travels as a tag derived from its name and your tree's root.

A taint name grants nothing on its own. An outsider is refused because of its credential, and a member can present only the taints its credential grants.

On the instance VeilNet hosts, conflux generates taints that are 26 symbols long, about 128 bits, for example brhk-2mq9-tzva-6pjs-k4xe-nw7d-qf.

Inspecting Taints

Issued Taints

To see the taints this machine was issued, run:

$ sudo conflux status

The taint row lists the taints in this machine's credential, or none: the realm's default compartment. It does not show a later move by a Taints order.

Data Peers

To see which peers this machine may exchange data with, run:

$ sudo conflux peers
ANCHOR      OVERLAY                                  IPV4        HARDWARE           STATE      CONN     DATA  REACH     RTT
i46dpakhug  fd80:c4b9:99ae:df9b:5261:d178:18f1:783c  10.128.0.2  ae:70:60:82:85:68  connected  out*,in  yes   nat-cone  990µs
s5g3oefl2s  fd80:c4b9:99ae:a015:58f1:5b6e:b140:5e8e  -           5a:f0:a9:da:4e:32  connected  out      no    unknown   1.2ms

Read the DATA column as follows:

  • DATA no on a peer you expected to reach usually means that taints are separating the two machines. Compare the two machines' taint rows character by character. Data flows only where one set contains the other.
  • DATA no on every peer can mean that this machine is blocked. To list the blocks in force, run sudo conflux anchorctl blocks on another member.

Reading or Moving a Member

To move another member to dev, run:

$ sudo conflux anchorctl taints -peer anchor6btpa3gn6w4stipba4hekzho7caw6srfyy5puvbz7mfanaiept5a -set dev

Without -set, the command reads the member's taints, shown as tags. Either way, the command sends a Taints order, so it needs:

  • the taint power in this machine's credential
  • a target member in the same realm
  • the target's full 58-character AnchorID