wirelineio / wns

Wireline Naming Service
GNU General Public License v3.0
0 stars 1 forks source link

Record spec. #274

Open richburdon opened 4 years ago

richburdon commented 4 years ago

Re: https://github.com/dxos/kube/issues/207

telackey commented 4 years ago

Short but important question about terms, does the "protocol" describe the fields which belong to the WNS record?

To use IPFS as the example, if I am registering an IPFS service record, and the type of the record is service and the protocol is [ wrn://dxos/protocol/service/ipfs ] what is the prospective content of wrn://dxos/protocol/service/ipfs ?

Is it:

  1. A description of the fields which my IPFS service record in WNS should/must contain.

  2. That, plus other things.

  3. Not that at all.

richburdon commented 4 years ago

@telackey No.

The schema for the Service record is fixed. It's defined by a protocol buffer message type that is part of the WNS code base. Similarly the schema of the Protocol record is fixed.

The CONTENTS of the Protocol record will be a set of protocol buffer type and service definitions. These text records will either be in a Protocol record field, or (more likely) linked via IPFS to a text document.

Service records may reference multiple Protocol records via the protocols field.

NOTE: The reason record TYPES are fixed is that they have specific fixed semantics that the network uses to operate. Protocol definitions on the other hand have semantics that are interpreted by individual services, apps, or bots (e.g., Chess Protocol, File Store Protocol).

telackey commented 4 years ago

OK, I am missing a piece then. Don't we need some other thing which describes what fields an IPFS service record needs to have vs what fields a Signal service record needs to have?

For example, a Signal server, at a minimum, to support bootstrapping other signal nodes, must have a bootstrap field; and if it is accessible by endusers, it must have a WebSocket URL for clients to use. (You could have a record with one but not the other: a service just offering bootstrapping, or one just used for servicing clients.)

record:
  type: 'service'
  ...
  bootstrap: 'signal.example.com:4000'
  url: 'wss://signal.example.com/dxos/signal'

An IPFS server on the other hand does not need any of these, but does need a field describing the IPFS protocol version being offered (not to be confused with our protocols) and an array of multiaddrs other IPFS servers can use to connect:

record:
  type: 'service'
  ...
  ipfs-protocol-version: 'ipfs/0.1.0',
  addresses:
     - '/ip4/208.69.42.151/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'
     - '/ip6/FF:FF:FF:99/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'
richburdon commented 4 years ago

OK good clear example.

So my feeling is there is a standard Record type for "service" records. What we might want is a payload field (not another record) that is typed by a protobuf schema. If we HAD to hack this today, we could do this by storing a JSON object in a key value field. I think this is close to what you want but: Rationale here is that this payload info is not queryable or separately addressable (which records are).

telackey commented 4 years ago

For clarity, my original proposal was something like this (the exact schema definition syntax is unimportant):

record:
  type: type
  name: ipfs
  version: 1.0.0
  schema:
    ipfs-protocol-version: String!
    addresses: [String!]!
wire wns set name wrn://dxos/type/service/ipfs <id>
record:
  type: wrn://dxos/type/service/ipfs
  ...
  ipfs-protocol-version: 'ipfs/0.1.0',
  addresses:
     - '/ip4/208.69.42.151/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'
     - '/ip6/FF:FF:FF:99/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'

I can query for types across the system if I want, or define my own within my namespace if nothing available fits.

So then, in a few days when I realize I need a "Signal Service" or a "TURN Service" that has different fields and requirements than an "IPFS Service", I repeat the process of registering the name of the service type first, then registering my service.

If we wanted to combine this with the universal parent type "service", perhaps it would be something like this:

record:
  type: service
  service: wrn://dxos/service/ipfs
  ...
  ipfs-protocol-version: 'ipfs/0.1.0',
  addresses:
     - '/ip4/208.69.42.151/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'
     - '/ip6/FF:FF:FF:99/tcp/29548/p2p/QmZrL5fSXKPM8UFCxKFdEBPdccziJgo7T4YeZLCPjzvUbq'
telackey commented 4 years ago

Using the payload example, perhaps it would be something like this:

record:
  type: service
  service: wrn://dxos/service/ipfs
  config: {
    "ipfs-protocol-version": "ipfs/0.1.0",
    "addresses" [ "....", "...." ]
  }
telackey commented 4 years ago

A disadvantage I can see to the unqueryable payload scheme is that if it is 2021 and I am running an "ipfs/0.2.0" server, querying for WHERE service = 'wrn://dxos/service/ipfs' AND ipfs-protocol-version = 'ipfs/0.2.0' is probably exactly what I want to do when choosing candidates for connection.

telackey commented 4 years ago

For reference it might also be worth noting what we have right now in the old WNS. There is mix of types, but most the service records look something like this (note that all existing types are prefixed with wrn:):

record:
  type: wrn:service
  name: signal1.dxos.network
  version: 1.0.0
  description: signal1.dxos.network
  service: ipfs
  ipfs:
    protocol: 'ipfs/0.1.0'
    addresses:
      - '/ip4/134.122.9.43/tcp/4001/p2p/QmUgmWfACwRafvAPTp2YBdNzezTDzZ1Tm7FF1PiEPxxHv8'

Type is always wrn:service, and there is a service: <name> attribute, so that one can query for type = 'wrn:service' AND service = 'ipfs'. By convention, service records have a map field named to match the value of the service field (eg, service: 'ipfs', ipfs: { ... } or service: 'signal', signal: { ... }.

The service: ipfs record schema is sketched out here: https://github.com/wirelineio/wns/blob/master/x/nameservice/SCHEMA.md#wns

The major difference between what we have and what is proposed is that the value of type (or perhaps service) ought to be a WNS-registered name referring to a formal schema record, rather than an arbitrary name with schema described informally in markdown.

richburdon commented 4 years ago

Following discussion with @dboreham

const services = [

  // A
  {
    id: 'wrn://dxos.network/service/my-ipfs-service',
    type: 'service',
    api: [
      {
        id: 'wrn://dxos.network/protocol/imap/0.0.1', // => protobuf schema
        muliAddr: ['192.168.1.100']
      },
      {
        id: 'wrn://dxos.network/protocol/smpt/0.0.2',
        muliAddr: ['192.168.1.100'],
        encrypted: true
      }
    ],
    payments: [
      {
        id: 'wrn://dxos.network/payment/state-channel/0.0.1', // => protobuf schema
        price: 'free'
      }
    ],
    meta: [
      {
        foo: 100
      }
    ]
  },

  // B
  {
    id: 'wrn://dxos.network/service/my-ipfs-service',
    type: 'service',
    serviceType: 'wrn://dxos.network/protocol/ipfs/0.0.1', // => protobuf schema
    price: 'free',
    multiAddr: ['192.168.1.100'],
    foo: 100
  }
];
AFDudley commented 4 years ago

NOTE: The reason record TYPES are fixed is that they have specific fixed semantics that the network uses to operate. Protocol definitions on the other hand have semantics that are interpreted by individual services, apps, or bots (e.g., Chess Protocol, File Store Protocol).

@richburdon @ashwinphatak Which network is being discussed here? WNS does not need Protocol definitions to operate. I assume Ashwin has already defined whatever protobufs are required for WNS to operate.