Files
Jędrzej Stuczyński a21a01cf1a node families (#6715)
* start node families topic branch

* start node families topic branch

* initialise node families contract

* define contract storage

* registering new family in storage

* accepting family invitation

* add_pending_invitation

* revoke_pending_invitation

* remove_family_member

* reject_pending_invitation

* disband_family

* added unit tests for the storage methods

* added restriction on uniquness of family names

* update rustc version for node families contract common

* clippy

* basic queries by id

* query_families_paged

* change family membership storage and expose query for all members of a family

* queries for pending invitations

* queries for past invitations

* queries for past data per node

* queries for past family members

* query_past_members_for_node_paged

* queries for family by name and by owner

* fixup family name normalisation

* fixed incorrect lower bound for queries for past data

* implement contract and storage initialisation

* stubbing tx messages that are to be exposed by the contract

* handler for updating config

* removed partial fee return

* wip: create family

* move mixnet contract interaction traits to shared location

* store original family name alongside the normalised variant

* prevent family creation if owner has a node in another family

* try_disband_family

* try_invite_to_family + shared helpers

* try_revoke_family_invitation

* accept_family_invitation

* stub method for node unbonding

* try_reject_family_invitation

* unit tests for family name normalisation

* try_leave_family

* try_kick_from_family

* fix outdated comments and add paid fee event attribute

* feat: NMv3: leave family upon node unbonding

* NF contract handling of unbonding

* lints

* init node families contract when creating performance contract tester

* clippy

* avoid self-dep in the contract dev deps

* introduced client traits for interacting with the node families contract

* add node families contract to cache refresher

* added query for all node family members (globally) and started scaffolding nym-api caches

* docs and cache -> api conversion

* calculating average node age based on individual timestamps

* wire up node families cache

* http stubs

* filled in the implementation

* route tests + extracting shared code

* review fixes

* feat: expose family information for all dvpn gateway endpoints within NS API

* expose family information for explorer v3 route

* clippy

* review comments and optimise db family update

* feat: Node Families: expose stake information inside DVpnGateway

* chore: update lock files after rebase

* chore: sort workspace members

* explicitly require providing node families contract address for mixnet contract migration

* fix missing node families contract address env export

* dont swallow cache overwrite failures in fixture

* pin network-defaults rustc version due to contracts dep

* further version pinning

* chore: update mixnet contract schema
2026-05-19 10:36:20 +01:00

621 lines
16 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "QueryMsg",
"description": "Query messages accepted by the contract.",
"oneOf": [
{
"description": "Look up a single family by its id.",
"type": "object",
"required": [
"get_family_by_id"
],
"properties": {
"get_family_by_id": {
"type": "object",
"required": [
"family_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Look up the (at most one) family owned by a given address.",
"type": "object",
"required": [
"get_family_by_owner"
],
"properties": {
"get_family_by_owner": {
"type": "object",
"required": [
"owner"
],
"properties": {
"owner": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Look up a single family by its name. The lookup is normalised contract-side (lowercased, non-alphanumerics stripped), so equivalent inputs resolve to the same family.",
"type": "object",
"required": [
"get_family_by_name"
],
"properties": {
"get_family_by_name": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_families_paged"
],
"properties": {
"get_families_paged": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Look up which family — if any — a node currently belongs to.",
"type": "object",
"required": [
"get_family_membership"
],
"properties": {
"get_family_membership": {
"type": "object",
"required": [
"node_id"
],
"properties": {
"node_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every node currently in a given family.",
"type": "object",
"required": [
"get_family_members_paged"
],
"properties": {
"get_family_members_paged": {
"type": "object",
"required": [
"family_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every current family member across all families, in ascending [`NodeId`] order. Each entry carries the membership record (which in turn names the family the node belongs to).",
"type": "object",
"required": [
"get_all_family_members_paged"
],
"properties": {
"get_all_family_members_paged": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Look up the pending invitation for a specific `(family_id, node_id)` pair.",
"type": "object",
"required": [
"get_pending_invitation"
],
"properties": {
"get_pending_invitation": {
"type": "object",
"required": [
"family_id",
"node_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"node_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every pending invitation issued by a given family.",
"type": "object",
"required": [
"get_pending_invitations_for_family_paged"
],
"properties": {
"get_pending_invitations_for_family_paged": {
"type": "object",
"required": [
"family_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every pending invitation issued for a given node.",
"type": "object",
"required": [
"get_pending_invitations_for_node_paged"
],
"properties": {
"get_pending_invitations_for_node_paged": {
"type": "object",
"required": [
"node_id"
],
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"node_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every pending invitation across all families.",
"type": "object",
"required": [
"get_all_pending_invitations_paged"
],
"properties": {
"get_all_pending_invitations_paged": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every archived (terminal-state) invitation issued by a given family.",
"type": "object",
"required": [
"get_past_invitations_for_family_paged"
],
"properties": {
"get_past_invitations_for_family_paged": {
"type": "object",
"required": [
"family_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every archived (terminal-state) invitation issued to a given node.",
"type": "object",
"required": [
"get_past_invitations_for_node_paged"
],
"properties": {
"get_past_invitations_for_node_paged": {
"type": "object",
"required": [
"node_id"
],
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"node_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every archived (terminal-state) invitation across all families.",
"type": "object",
"required": [
"get_all_past_invitations_paged"
],
"properties": {
"get_all_past_invitations_paged": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "array",
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every archived membership record for a given family (nodes that used to belong to it but have since been removed).",
"type": "object",
"required": [
"get_past_members_for_family_paged"
],
"properties": {
"get_past_members_for_family_paged": {
"type": "object",
"required": [
"family_id"
],
"properties": {
"family_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Page through every archived membership record for a given node (every family the node used to belong to but has since been removed from), across all families.",
"type": "object",
"required": [
"get_past_members_for_node_paged"
],
"properties": {
"get_past_members_for_node_paged": {
"type": "object",
"required": [
"node_id"
],
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"node_id": {
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"array",
"null"
],
"items": [
{
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
{
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
],
"maxItems": 2,
"minItems": 2
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
]
}