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
43 changes: 43 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
I was thinking about this some more and what might be some desired things to put in rawhex. Here's my thoughts so far.

0 = Nostr Pubkey in Hex 64 hex digits 0x40
040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282

1 = Nostr Relay[ws] (IP, DNS, Spaces) relay.primal.net, relay.primal.net, relay@primal ex: ws://194.195.222.47:4848/
2 = Nostr Relay[wss] (IP, DNS, Spaces) relay.primal.net, relay.primal.net, relay@primal ex: wss://relay.primal.net/

3 = Pubky.app Pubkey = 7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy
37666D6A706375757A6635346877313862736769337A69687A7968346177736565757135746D6F6A656661657A6A626436346379

4 = Decentralized ID example = did:btc1 identifier Hex 136 hex digits 0x88
did:btc1:k1q0rnnwf657vuu8trztlczvlmphjgc6q598h79cm6sp7c4fgqh0fkc0vzd9u:
3886469643A627463313A6B317130726E6E77663635377675753874727A746C637A766C6D70686A67633671353938683739636D3673703763346667716830666B6330767A6439753A

5 = DNS A (IPV4 or IPV6 as hex)
6 = DNS CNAME (DNS, Spaces) www.example.com, www@example, @otherspace, www.example.spaces
7 = DNS SMTP (IP, DNS, Spaces) in1-smtp.messagingengine.com
8 = DNS TXT (Arbitrary ASCII)
9 = Bitcoin wallet address ex: bc1pjeda67ewjtms6p20nk3udt6c5wwk90zzdlhd3dx73r8ynzsm07nqwxggmu
A = Ethereum wallet address ex: 0xC3P0F36260817d1c78C471406BdE482177a1935071
B = Unused 11
C = Unused 12
D = Unused 13
E = Unused 14
F = Unused 15

Here's an example data payload that would contain both a Nostr pubkey and a did:btc1 identifier.

3+64+3+136=206 bytes to hold 2 data types(Nostr Pubkey + did)
040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b42823886469643A627463313A6B317130726E6E77663635377675753874727A746C637A766C6D70686A67633671353938683739636D3673703763346667716830666B6330767A6439753A

Here's an example data payload that would contain both a Nostr pubkey and 2 relays and a Bitcoin address

3+64+3+22+3+35+3+84=217 bytes to hold 4 data elements(Nostr Pubkey + relay@damus + relay.primal.net + bc1p...ggmu )
64
040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282 \
22
1 72656C61794064616D7573 \ relay@damus (recursive lookup -> ws://192.168.1.254/)
35
2 72656C61792E7072696D616C2E6E6574 \ relay.primal.net
84
9 62633171717067656379353433767A636770666A64746D746C7A3672357563367472676668686D336D6E \Bech32? p2wpkh bc1qqpgecy543vzcgpfjdtmtlz6r5uc6trgfhhm3mn
51 changes: 51 additions & 0 deletions RESOLVER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
### Given john@doe and nothing else, how do we determine if it's valid and if so return associated meta-data?


```javascript

// Parse the handle into subname and top-level space
let (subname, space) = handle.split('@');

// Check if the space is a valid space using space-cli getspace
space-cli getspace '@'+space

// If the result is null, then the space is not valid
if (result === null) {
return null;
}

// Otherwise, parse out the covenant.data as a hex string

// Process the hex string per SIPXX

// The first byte is the version byte

// If the version is not 0x01, return null
if (version !== 0x01) {
return null;
}

// While there is more bytes to process
// Get the next byte as the type and following length byte
// Get the value as the next length bytes of data
// Switch on the type and process the value accordingly
// If the type is not recognized, return null
// If the value is valid, interpret the value accordingly
// Case type of:
// 0x00 | Owner URI | RPC Interface | `http://192.168.1.254:8080/v1/services/getspace` |
// 0x01 | Owner Web | Info Website | `https://spacesops.com` |
//0x02 | Nostr Pubkey | 64 hex digits (32 bytes) | `040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282` |
//0x03 | Nostr Relay | WebSocket relay (IP, DNS, Spaces) | `wss://relay@primal,wss://relay.primal.net,ws://194.195.222.47:4848/` |

// Prior to proof commitment, only the space operator knows if a subname is valid or not.

// If an operator gets a request for a handle for a space it doesn't control, does it act as a proxy and forward the request to the space operator? Can it cache results? If so for how long?

// If information is not found in the "data", then try the fabric node net for data.
// Can a subspace owner create/sign/publish zones just for john@doe?
// If all this fails then return null.

// If the hex string is not valid, return null
return null;

```
94 changes: 94 additions & 0 deletions SCHEMA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# VTLV Schema Specification

## Overview

This document defines a Version-Type-Length-Value (VTLV) binary encoding scheme for storing multiple data types in a single payload. The schema supports up to 255 different data types and allows for protocol versioning.

## Format Structure

```
[Version: 1 byte][Type: 1 byte][Length: 1 byte][Value: N bytes]
```

- **Version (1 byte)**: Protocol version (0-255)
- **Type (1 byte)**: Data type identifier (0-255)
- **Length (1 byte)**: Length of value payload (0-255 bytes)
- **Value (N bytes)**: Actual data payload

## Data Types

| Type | Name | Description | Example Value |
|------|------|-------------|---------------|
| 0x00 | Owner URI | RPC Interface | `http://192.168.1.254:8080/v1/services/getspace` |
| 0x01 | Owner Web | Info Website | `https://spacesops.com` |
| 0x02 | Nostr Pubkey | 64 hex digits (32 bytes) | `040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282` |
| 0x03 | Nostr Relay | WebSocket relay (IP, DNS, Spaces) | `wss://relay@primal,wss://relay.primal.net,ws://194.195.222.47:4848/` |
| 0x04 | Pubky.app Pubkey | Pubky.app identifier | `pk:7fmjpcuuzf54hw18bsgi3zihzyh4awseeuq5tmojefaezjbd64cy` |
| 0x05 | Decentralized ID | DID identifier (68 bytes hex) | `did:btc1:k1q0rnnwf657vuu8trztlczvlmphjgc6q598h79cm6sp7c4fgqh0fkc0vzd9u:` |
| 0x06 | DNS A Record | IPv4/IPv6 address as hex | IPv4/IPv6 hex representation |
| 0x07 | DNS CNAME | Canonical name (DNS, Spaces) | `www.example.com`, `www@example` |
| 0x08 | DNS SMTP | SMTP server address | `in1-smtp.messagingengine.com` |
| 0x09 | DNS TXT | Arbitrary ASCII text | Any ASCII string |
| 0x0A | Bitcoin Address | Bitcoin wallet address | `bc1pjeda67ewjtms6p20nk3udt6c5wwk90zzdlhd3dx73r8ynzsm07nqwxggmu` |
| 0x0B | Ethereum Address | Ethereum wallet address | `0xC3P0F36260817d1c78C471406BdE482177a1935071` |
| 0x0C-0xFF | Reserved | Unused types | Reserved for future use |

## Payload Examples

### Example 1: Nostr Pubkey + DID
```
Version: 0x01
Type: 0x00, Length: 0x40, Value: 040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282
Type: 0x04, Length: 0x88, Value: 3886469643A627463313A6B317130726E6E77663635377675753874727A746C637A766C6D70686A67633671353938683739636D3673703763346667716830666B6330767A6439753A
```

### Example 2: Nostr Pubkey + 2 Relays + Bitcoin Address
```
Version: 0x01
Type: 0x00, Length: 0x40, Value: 040e739ce127b6d77c34ea12e10245b72742a26c67ce0575c3b0add38dc297b4282
Type: 0x01, Length: 0x16, Value: 72656C61794064616D7573
Type: 0x02, Length: 0x23, Value: 72656C61792E7072696D616C2E6E6574
Type: 0x09, Length: 0x54, Value: 62633171717067656379353433767A636770666A64746D746C7A3672357563367472676668686D336D6E
```

## Implementation Notes

1. **Version Field**: Currently set to 0x01. Increment for protocol changes.
2. **Type Field**: Limited to 0-255 (0x00-0xFF) as specified.
3. **Length Field**: Limited to 0-255 bytes per value payload.
4. **Multiple Records**: Multiple VTLV records can be concatenated in sequence.
5. **Endianness**: All multi-byte fields use big-endian byte order.
6. **Padding**: No padding between records - records are tightly packed.

## Parsing Algorithm

```javascript
function parseVTLV(buffer) {
const records = [];
let offset = 0;

while (offset < buffer.length) {
if (offset + 3 > buffer.length) break; // Need at least V+T+L

const version = buffer[offset++];
const type = buffer[offset++];
const length = buffer[offset++];

if (offset + length > buffer.length) break; // Not enough data

const value = buffer.slice(offset, offset + length);
offset += length;

records.push({ version, type, length, value });
}

return records;
}
```

## Error Handling

- **Invalid Length**: If length field exceeds remaining buffer, skip record
- **Unknown Type**: Parser should preserve unknown types for future compatibility
- **Version Mismatch**: Parser should handle multiple versions gracefully
- **Truncated Data**: Detect and report incomplete records
31 changes: 31 additions & 0 deletions sip-horologger-data-format.mediawiki
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
SIP: X
Title: Data format of getspace.covenant.data & getptr.data
Author: horologger (horologger@protonmail.com)
Status: Draft
Type: Standards Track
Created: 2025-10-27
License: BSD-2-Clause
Discussions-To: [TBD]


==Abstract==


==Motivation==


==Specification==


==Rationale==


==Backwards Compatibility==


==Reference Implementation==


==Copyright==

This SIP is licensed under the BSD-2-Clause License.