Passport

Passport is a system of chained-signatures which allows a set of wallet addresses to attest to certain properties. Basically the passport is a typical user profile with things like display-name avatar bio etc, except it's all tied to ethereum addresses, and signed by those addresses to prove that this info came from this wallet. This system forms the basis for a decentralized, verifiable, cryptographic identity. Within urbit, this system is implemented as an agent %passport, which uses %bedrock to store the chain links and current passport state, and serves them up on request (if the passport is marked as discoverable)

details

The passport type is defined in bedrock as:

+$  passport
  $:  =contact
      cover=(unit @t)
      user-status=?(%invisible %online)
      discoverable=?
      nfts=(list linked-nft)
      addresses=(list linked-address)
      default-address=@t
      recommendations=(set rich-ref)
      chain=passport-chain
      crypto=passport-crypto
  ==

But really, all that is needed to reconstruct the whole thing is the chain=passport-chain which is an ordered list of passport-link-containers

+$  passport-chain  (list passport-link-container)
+$  passport-link-container   [link-type=@t data=@t hash=@t hash-signature=@t]

From this information, any system, urbit or javascript or whatever, that knows the passport specification, can reconstruct all the other fields. The reference implementation for this lives at https://github.com/holium/signature-chain-js

There is a lot of metadata associated with the passport system, but at it's core, it's a series of fairly simple "links" which describe some change to the passport state that is being made, which means that the current passport state is just the result of applying all the links in order. The specified links are:

+$  passport-link
  $%  [%edge-add from-link-hash=@t to-link-hash=@t key=@t value=@t]
      [%edge-remove link-hash=@t]
      [%entity-add address=@t address-type=@t name=@t]
      [%entity-remove name=@t]
      [%key-add address=@t address-type=@t name=@t]
      [%key-remove address=@t]
      [%post-add type=@t data=json]
      [%post-edit link-hash=@t type=@t data=json]
      [%post-remove link-hash=@t]
      [%name-record-set name=@t record=@t]
      [%token-burn from-entity=@t amount=@rd]
      [%token-mint to-entity=@t amount=@rd]
      [%token-transfer to-entity=@t amount=@rd]
  ==

but currently the only necessary ones are %name-record-set %key-add %key-remove and the initial PASSPORT_ROOT link.

example

an sample passport record coming back from the /our-passport.json scry

{
    "nfts": [
        {
            "token-standard": "ERC721",
            "name": "Bored Ape Nike Club",
            "contract-address": "0x000386E3F7559d9B6a2F5c46B4aD1A9587D59Dc3",
            "token-id": "1",
            "image-url": "https://i.seadn.io/gae/yJ9DgXqjRwgdCkrQmHj7krCbixM8fPVAyYJWJ5NHXap1L0c3QL5MPvrNT0QDINIStGOK857lOvab8MpNQS9X4pkHPktmhVmN82qoVw?w=500&auto=format",
            "chain-id": "eth-mainnet",
            "owned-by": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
        }
    ],
    "cover": null,
    "discoverable": true,
    "contact": {
        "avatar": {
            "img": "https://steamavatar.io/img/1477787732RP7QJ.jpg",
            "type": "nft"
        },
        "bio": "Just another test moon",
        "ship": "~ribfer-dozset-tolwer-mogmer",
        "display-name": "Paul",
        "color": "#B17BD7"
    },
    "user-status": "online",
    "recommendations": [],
    "crypto": {
        "pki-state": {
            "entity-to-value": {
                "passport_root": 1728
            },
            "address-to-entity": {
                "0xB983B84AD18A92448727647Ff98EC95Fd2201C9A": "passport_root",
                "0x9b3D8208357155c9962EcE54C124C26ca907c3fE": "passport_root"
            },
            "address-to-nonce": {
                "0xB983B84AD18A92448727647Ff98EC95Fd2201C9A": 0,
                "0x9b3D8208357155c9962EcE54C124C26ca907c3fE": 3
            },
            "chain-owner-entities": [
                "passport_root"
            ],
            "entity-to-addresses": {
                "passport_root": [
                    "0x9b3D8208357155c9962EcE54C124C26ca907c3fE",
                    "0xB983B84AD18A92448727647Ff98EC95Fd2201C9A"
                ]
            }
        },
        "previous-epoch-hash": "0x00000000000000000000000000000000",
        "sig-chain-settings": {
            "epoch-length": 12,
            "data-state": {
                "NAME_RECORD": {}
            },
            "signing-key": "0x9b3D8208357155c9962EcE54C124C26ca907c3fE",
            "new-entity-balance": 144
        },
        "timestamp": 1696956121813,
        "data-block-number": 0,
        "data-structs": {
            "struct-names": [
                "NAME_RECORD"
            ],
            "struct-types": ""
        },
        "transaction-types": {
            "link-structs": "",
            "link-names": [
                "ENTITY_ADD",
                "ENTITY_REMOVE",
                "KEY_ADD",
                "SIGNED_KEY_ADD",
                "KEY_REMOVE",
                "NAME_RECORD_SET"
            ]
        },
        "epoch-block-number": 0,
        "link-id": "PASSPORT_ROOT"
    },
    "addresses": [
        {
            "crypto-signature": {
                "signature-of-hash": "0x43de123e0d869f266a49e15fb8ea26d4bc52d8d50328cbb77fb870f8f4686069234bfc35a5cf57b81411f28ff89dcf13d9503d273baa14d9842baf121b6897e51c",
                "data": "{\"link-id\":\"PASSPORT_ROOT\",\"epoch-block-number\":0,\"data-block-number\":0,\"timestamp\":1696956121813,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"pki-state\":{\"chain-owner-entities\":[\"passport_root\"],\"entity-to-addresses\":{\"passport_root\":[\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\"]},\"address-to-nonce\":{\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\":0},\"entity-to-value\":{\"passport_root\":1728},\"address-to-entity\":{\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\":\"passport_root\"}},\"transaction-types\":{\"link-names\":[\"ENTITY_ADD\",\"ENTITY_REMOVE\",\"KEY_ADD\",\"SIGNED_KEY_ADD\",\"KEY_REMOVE\",\"NAME_RECORD_SET\"],\"link-structs\":\"\"},\"data-structs\":{\"struct-names\":[\"NAME_RECORD\"],\"struct-types\":\"\"},\"sig-chain-settings\":{\"new-entity-balance\":144,\"epoch-length\":12,\"signing-key\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"data-state\":{\"NAME_RECORD\":{}}}}",
                "hash": "0x5f620570e881079da666cc52904e0be7cfcb4a422dd51a4623a38e65b4b09355",
                "pubkey": "0x04895002135c9fd32d766daa76bf0e53e7b1c310cd35ca7443e986ee3a87a152cfefd1202406534faf4ed71990de8b955c8d130b96109e9bf7f92882f5dfdad5c4"
            },
            "address": "0x9b3D8208357155c9962EcE54C124C26ca907c3fE",
            "wallet": "metamask",
            "pubkey": "0x04895002135c9fd32d766daa76bf0e53e7b1c310cd35ca7443e986ee3a87a152cfefd1202406534faf4ed71990de8b955c8d130b96109e9bf7f92882f5dfdad5c4"
        },
        {
            "crypto-signature": {
                "signature-of-hash": "0x999fcb1da0e56f1ac0d6a26db510697231d68ebcabe9b85f1846c4c859c0b97505fa240a0c37d0627780dd4df9591900df6b68038c351e281d5e64849901b5f11b",
                "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"value\":1,\"link-id\":\"SIGNED_KEY_ADD\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":1,\"nonce\":1,\"previous-link-hash\":\"0x9fdfe548ffd5d3512860491d0658f1e3bd8fea25594f7a329fb429f1ebdca3d2\",\"timestamp\":1696956121821},\"link-data\":{\"address\":\"0xB983B84AD18A92448727647Ff98EC95Fd2201C9A\",\"address-type\":\"metamask\",\"entity-name\":\"passport_root\",\"address-signature\":\"0x1fcfa16264d640480517e164c7254a584f84cebcac572627578b9e868b56800e2b8fa2124765ace4c1284a6c6020f4d0451887892488a069a83e09fe0a25abaa1c\"}}",
                "hash": "0xb343610b36b9a03ce6dc5bd4f6f3c584858841be8f8c2f2b7f2563f4d1885cc8",
                "pubkey": "0x04895002135c9fd32d766daa76bf0e53e7b1c310cd35ca7443e986ee3a87a152cfefd1202406534faf4ed71990de8b955c8d130b96109e9bf7f92882f5dfdad5c4"
            },
            "address": "0xB983B84AD18A92448727647Ff98EC95Fd2201C9A",
            "wallet": "metamask",
            "pubkey": "0x04fbda43a08ce19ee7b405efede4db2ec6f835417843a3faba90d0976239fe1768de1a3c860967f5292a249f9f37b298c776435d1954e3385c04e751ff2e2ef4b1"
        }
    ],
    "default-address": "0x9b3D8208357155c9962EcE54C124C26ca907c3fE",
    "chain": [
        {
            "signature-of-hash": "0x43de123e0d869f266a49e15fb8ea26d4bc52d8d50328cbb77fb870f8f4686069234bfc35a5cf57b81411f28ff89dcf13d9503d273baa14d9842baf121b6897e51c",
            "link-type": "PASSPORT_ROOT",
            "data": "{\"link-id\":\"PASSPORT_ROOT\",\"epoch-block-number\":0,\"data-block-number\":0,\"timestamp\":1696956121813,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"pki-state\":{\"chain-owner-entities\":[\"passport_root\"],\"entity-to-addresses\":{\"passport_root\":[\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\"]},\"address-to-nonce\":{\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\":0},\"entity-to-value\":{\"passport_root\":1728},\"address-to-entity\":{\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\":\"passport_root\"}},\"transaction-types\":{\"link-names\":[\"ENTITY_ADD\",\"ENTITY_REMOVE\",\"KEY_ADD\",\"SIGNED_KEY_ADD\",\"KEY_REMOVE\",\"NAME_RECORD_SET\"],\"link-structs\":\"\"},\"data-structs\":{\"struct-names\":[\"NAME_RECORD\"],\"struct-types\":\"\"},\"sig-chain-settings\":{\"new-entity-balance\":144,\"epoch-length\":12,\"signing-key\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"data-state\":{\"NAME_RECORD\":{}}}}",
            "hash": "0x5f620570e881079da666cc52904e0be7cfcb4a422dd51a4623a38e65b4b09355"
        },
        {
            "signature-of-hash": "0xba7f289e39a6cd6ab23bccae63978334316098d3419577fbfc8bf563a3c7d71b2ad60d83156657eae1ef74ab82f3b2caa6c3b8e70a05e45fa6469dacc0ffc7021b",
            "link-type": "KEY_ADD",
            "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"value\":1,\"link-id\":\"KEY_ADD\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"nonce\":0,\"previous-link-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":0,\"timestamp\":1696956121818},\"link-data\":{\"address\":\"0x2869176b453C675fB78f120AcF2BFa6FA816b0A5\",\"address-type\":\"metamask\",\"entity-name\":\"passport_root\"}}",
            "hash": "0x9fdfe548ffd5d3512860491d0658f1e3bd8fea25594f7a329fb429f1ebdca3d2"
        },
        {
            "signature-of-hash": "0x999fcb1da0e56f1ac0d6a26db510697231d68ebcabe9b85f1846c4c859c0b97505fa240a0c37d0627780dd4df9591900df6b68038c351e281d5e64849901b5f11b",
            "link-type": "SIGNED_KEY_ADD",
            "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"value\":1,\"link-id\":\"SIGNED_KEY_ADD\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":1,\"nonce\":1,\"previous-link-hash\":\"0x9fdfe548ffd5d3512860491d0658f1e3bd8fea25594f7a329fb429f1ebdca3d2\",\"timestamp\":1696956121821},\"link-data\":{\"address\":\"0xB983B84AD18A92448727647Ff98EC95Fd2201C9A\",\"address-type\":\"metamask\",\"entity-name\":\"passport_root\",\"address-signature\":\"0x1fcfa16264d640480517e164c7254a584f84cebcac572627578b9e868b56800e2b8fa2124765ace4c1284a6c6020f4d0451887892488a069a83e09fe0a25abaa1c\"}}",
            "hash": "0xb343610b36b9a03ce6dc5bd4f6f3c584858841be8f8c2f2b7f2563f4d1885cc8"
        },
        {
            "signature-of-hash": "0x8ee53925542b80b538d0d1d22ddaa7024ab002ab0a58ffed1816119200e5384c1de512fc6e6bb4f2fb7b2e1510ffb56b8ed102f22608b9d0e3aaa2d305b1e4281b",
            "link-type": "NAME_RECORD_SET",
            "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x2869176b453C675fB78f120AcF2BFa6FA816b0A5\",\"value\":1,\"link-id\":\"NAME_RECORD_SET\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":2,\"nonce\":2,\"previous-link-hash\":\"0xb343610b36b9a03ce6dc5bd4f6f3c584858841be8f8c2f2b7f2563f4d1885cc8\",\"timestamp\":1696956121824},\"link-data\":{\"name\":\"display-name\",\"record\":\"Paul\"}}",
            "hash": "0x67c06d2f48fbf74d899126150cf3651037ae2cb5a3a6eee660380bed83a473c0"
        },
        {
            "signature-of-hash": "0x021383b4b2bc140d13f6c21f8a25f1e447e4a631d35b70e8795d4497dbb830ce68ffb5a300adba8d50d6d2b53392e4dfec5f30b70a865b00a59e063ed7044e4c1b",
            "link-type": "NAME_RECORD_SET",
            "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"value\":1,\"link-id\":\"NAME_RECORD_SET\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":3,\"nonce\":3,\"previous-link-hash\":\"0x67c06d2f48fbf74d899126150cf3651037ae2cb5a3a6eee660380bed83a473c0\",\"timestamp\":1696956121826},\"link-data\":{\"name\":\"nfts\",\"record\":\"[{\\\"chain-id\\\":\\\"eth-mainnet\\\",\\\"token-id\\\":\\\"1\\\",\\\"contract-address\\\":\\\"0x000386E3F7559d9B6a2F5c46B4aD1A9587D59Dc3\\\",\\\"name\\\":\\\"Bored Ape Nike Club\\\",\\\"image-url\\\":\\\"https://i.seadn.io/gae/yJ9DgXqjRwgdCkrQmHj7krCbixM8fPVAyYJWJ5NHXap1L0c3QL5MPvrNT0QDINIStGOK857lOvab8MpNQS9X4pkHPktmhVmN82qoVw?w=500&auto=format\\\",\\\"owned-by\\\":\\\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\\\",\\\"token-standard\\\":\\\"ERC721\\\"}]\"}}",
            "hash": "0x0a49aa9d1cddd188603e1fcca4c66b07446805e6c8cd6a1e73057bcdf42fbd3a"
        },
        {
            "signature-of-hash": "0xcf988407c6097fd745f84c00644aa47c1fbbbf5cb0368ff5963489ec634ab8374ad95152e7e59d735fc0c93a0d85c37cb4104f305be1e295d20625a1270588e51b",
            "link-type": "KEY_REMOVE",
            "data": "{\"link-metadata\":{\"from-entity\":\"passport_root\",\"signing-address\":\"0x9b3D8208357155c9962EcE54C124C26ca907c3fE\",\"value\":1,\"link-id\":\"KEY_REMOVE\",\"epoch-block-number\":0,\"previous-epoch-nonce\":0,\"previous-epoch-hash\":\"0x00000000000000000000000000000000\",\"data-block-number\":4,\"nonce\":4,\"previous-link-hash\":\"0x0a49aa9d1cddd188603e1fcca4c66b07446805e6c8cd6a1e73057bcdf42fbd3a\",\"timestamp\":1696956121835},\"link-data\":{\"address\":\"0x2869176b453C675fB78f120AcF2BFa6FA816b0A5\"}}",
            "hash": "0x08860471ad00cb98cc867bda97c49f9877998801812b8bf27edefa297c27bfae"
        }
    ]
}

misc

The %passport agent also handles contacts and friends.

Friends are just a representation of the relationship between two ships:

+$  friend
  $:  =ship
      ::pending-outgoing = WE asked `ship` to be friend
      ::pending-incoming = `ship` asked US to be friend
      ::friend = pending `ship` accepted to be friend
      ::rejected = pending `ship` rejected to be friend
      status=?(%pending-outgoing %pending-incoming %friend %rejected)
      pinned=?
      mtd=(map @t @t)
  ==

Contacts are a miniature, unverified snapshot of some of a ship's passport information, for the sake of quick ui rendering and richer ship-search.

+$  contact
  $:  =ship
      avatar=(unit avatar)
      color=(unit @t) :: i.e. #FCFCFC
      bio=(unit @t)
      display-name=(unit @t)
  ==

Last updated