Wolfram Computation Meets Knowledge

New in 13: Cryptography, Blockchains & NFTs

Two years ago we released Version 12.0 of the Wolfram Language. Here are the updates in cryptography, blockchains and NFTs since then, including the latest features in 13.0. The contents of this post are compiled from Stephen Wolfram’s Release Announcements for 12.1, 12.2, 12.3 and 13.0.

 

Cryptography & Security (December 2020)

One of the things we want to do with Wolfram Language is to make it as easy as possible to connect with pretty much any external system. And in modern times an important part of that is being able to conveniently handle cryptographic protocols. And ever since we started introducing cryptography directly into the Wolfram Language five years ago, I’ve been surprised at just how much the symbolic character of the Wolfram Language has allowed us to clarify and streamline things to do with cryptography.

A particularly dramatic example of this has been how we’ve been able to integrate blockchains into Wolfram Language (and Version 12.2 adds bloxberg with several more on the way). And in successive versions we’re handling different applications of cryptography. In Version 12.2 a major emphasis is symbolic capabilities for key management. Version 12.1 already introduced SystemCredential for dealing with local “keychain” key management (supporting, for example, “remember me” in authentication dialogs). In 12.2 we’re also dealing with PEM files.

If we import a PEM file containing a private key we get a nice, symbolic representation of the private key:

private = First
&#10005

private = First[Import["ExampleData/privatesecp256k1.pem"]]

Now we can derive a public key:

public = PublicKey
&#10005

public = PublicKey[%]

If we generate a digital signature for a message using the private key

GenerateDigitalSignature
&#10005

GenerateDigitalSignature["Hello there", private]

then this verifies the signature using the public key we’ve derived:

VerifyDigitalSignature
&#10005

VerifyDigitalSignature[{"Hello there", %}, public]

An important part of modern security infrastructure is the concept of a security certificate—a digital construct that allows a third party to attest to the authenticity of a particular public key. In Version 12.2 we now have a symbolic representation for security certificates—providing what’s needed for programs to establish secure communication channels with outside entities in the same kind of way that https does:

Import
&#10005

Import["ExampleData/client.pem"]

Blockchain, Storage, Authentication & Cryptography (May 2021)

We first introduced blockchain functionality into Wolfram Language in Version 11.3 (2018), and in each successive version we’re adding more and more blockchain integration. Version 12.3 adds connectivity to the Tezos blockchain:

&#10005

BlockchainBlockData[-1, BlockchainBase -> "Tezos"]

&#10005

<|"BlockHash" -> 
  "BKp9B8Z4zNpMDeSaFe2ZU6tywVUhady46Jji1oizxkRc4WGwpkf", 
 "BlockNumber" -> 1460305, 
 "PreviousBlockHash" -> 
  "BL8qGr1awP9RdeCMRExVvyiVadHJvzo9AJGMTfwnWEZDh8BAZf1", 
 "Protocol" -> "PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA", 
 "NextProtocol" -> 
  "PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA", 
 "Timestamp" -> 
  DateObject[{2021, 5, 6, 15, 23, 25.`}, "Instant", 
   "Gregorian", -4.`], "ValidationPass" -> 4, 
 "OperationsHash" -> 
  "LLoatzgmfL7B8dz5tdJu6RncRTXmPSBHxNpwbAuKyNc4daJw21m9V", 
 "Fitness" -> {"01", "00000000000c4851"}, 
 "ContextHash" -> 
  "CoVdfkgRAo5QFd5iqhoKX34s4KcaZSTgSee7TsPwmCFaLch7TSnu", 
 "Priority" -> 0, "Nonce" -> "cbbfffdbf95d0300", 
 "Signature" -> DigitalSignature[
Association[
   "Type" -> "EllipticCurve", "CurveName" -> "prime256v1", "R" -> 
    ByteArray[{63, 206, 128, 26, 8, 98, 13, 127, 155, 77, 28, 109, 
      127, 131, 181, 72, 12, 233, 255, 113, 50, 41, 68, 60, 176, 134, 
      219, 28, 96, 233, 234, 145}], "S" -> 
    ByteArray[{203, 169, 245, 106, 175, 234, 118, 156, 176, 232, 249, 
      67, 153, 193, 64, 177, 95, 75, 47, 32, 23, 90, 41, 184, 8, 242, 
      92, 126, 135, 75, 109, 18}], "SignatureType" -> "Deterministic",
     "HashingMethod" -> None]], Sequence[
 "ConsumedGas" -> 791549625, "Baker" -> 
  "tz3RB4aoyjov4KEVRbuhvQ1CKJgBJMWhaeB8", "BlockReward" -> 
  Quantity[40000000, "Mutez"], "BlockFees" -> 
  Quantity[452892, "Mutez"], "TotalTransactions" -> 61, 
  "TransactionList" -> {
   "op6VomseCtH7rizEpty4e1kATAP2wZ95Zc2TnciUHgHDxsjAks4", 
    "opTjVuymKZuSgAvLq7QzfAn6pqgSJzFyYQx2ZYKA8J9AKYjGbUE", 
    "opNNDhSkp2j1s9MNyaH7nW4T8gREpPnDN7zPwnoxS2Q74EzRJYS", 
    "op9Sy24XKKJxwJ1UyBZ4didiyi6TtgDj2rMstCnYmPs9MLyCGra", 
    "oozW8QwRnGvde4yqf1P4xM99Nzb5o1tg4RHRJg3uVEWjYVG1Afw", 
    "op6EFngrBovURGURpKNsbz22r5bcRPaM4XbYCarStWG25X2kuJH", 
    "ooFkZjFM33UjXDLvkhkD1SNUguh8rnnLfmwFefS7YWNR2tCpfVA", 
    "onqdtnVexw5jsxy4P1FTbYRwBcNH1DrppjWgryCv32qqqw1Y7aP", 
    "ooCgPPZi75TbErNqUEpptUvx6mU9T8B1DCsaU4eJYtbrishZqGw", 
    "onudTXp25r5Zf2aZyMMKUAAFzqVQX24jwPNCN2TFPVQEA6hiEMk", 
    "op8eRJ5T3yMLDSzSbH4EA1VpA91VaMECCy6uGASfE1aNVWuu8tb", 
    "onpbU1aussshJatN8xfvqFWn3hNuDUZRD8SSem1XMrkcnnkRPwR", 
    "onwvab7jYybdAX8fmG7ntMXVgQoT1UXi8hHJDiuMu9DmHT7hsDV", 
    "ooPqN4ejaPjbuvn9aoGUzdj7Jb68Sp3CT4WV6ysvrvdEhSjw11u", 
    "oo9YcyDUZiJN5r6nTtr5uU2d6WgFuxby8zygjNbFUAkMbcq2Kkc", 
    "oojLDHmjFXpgcEdLrtu1ri5fkYyMLcxZVw4jxF2TZ3f7ELFkkwu", 
    "oo5znRzP43gSP5TKwaBHD96zkt4xw3QfRqEXFiXAEuUxTn9SDeL", 
    "ooqYjZ6boQBtVxRsBqrHxB9vmJRFkPAYysR2iaXigEQ6NepgDiV", 
    "ooETrujpf9SuB5ErLheg653puC7NEKA1DFLEZHttEBMVa7HaNJa", 
    "opAHbY3xtTUhekjv8Kgzvv6GS1uK3S4Arz5ygJiEVRZu8hSv7Vi", 
    "oodaSNWZfzyUHXa94pJ9vohwZS4FbEmtuZgMZnwf9WJ2mqkDcTW", 
    "oouk2fBfhWPirfcNzdxXKxhDtnyMnvK65hD1MnHPApFuesFuuMt", 
    "opRcK6KBE1Y79GyGzmYsqRPZntxsV1A2gRK4iVZ91x573H1nTRp", 
    "opZVSQx9cVe4rxAv81eurea9GisjyFJc9DdKEiPSpgCB8aUtHG9", 
    "oogML3KCzAZZE1aaagcpXwfoa9R7zqdiiQHC9LT5j6ZcnsfY6P7", 
    "oouk2fBfhWPirfcNzdxXKxhDtnyMnvK65hD1MnHPApFuesFuuMt", 
    "opRcK6KBE1Y79GyGzmYsqRPZntxsV1A2gRK4iVZ91x573H1nTRp", 
    "opZVSQx9cVe4rxAv81eurea9GisjyFJc9DdKEiPSpgCB8aUtHG9", 
    "onvdAawno4HEbLJhS1St7j3RFaCi7rDZSeAzC1DM7Cafs1EadMJ", 
    "onqyJ3Cin5sxuWPvZgcVqXqBeTNFijkthcrz5bS4U8ATwhzodHK", 
    "op2hL6BVZg6y8zzQKQWzk5Bxs8Cr89QCSocFaYoNTVPvAXnQ4Hu", 
    "onijR1dKbGM1zR9dAbasxactqGQC4z6J6b4Uzrccy4vAnCD4Fn7", 
    "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
    "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
    "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
    "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
    "onyUVr21aiaYCL8cQFSZ8S7iMtu3qKRmycWAMwrUELJ6Y8UWkr5", 
    "op2ZjLMAGz9N8uMwDF1eUt4SwPviLHvGEHLukB88vWVTkx4daT7", 
    "onpABZgtFEYCNQNJPDNX56M4UEbyekKY9NibBQw9x11KTqiaCbE", 
    "oogML3KCzAZZE1aaagcpXwfoa9R7zqdiiQHC9LT5j6ZcnsfY6P7", 
    "opPWXEj2p6MHCGfon4nZGVnG3zBXWY2CZtYVRRjVNDBvQPLxnUU", 
    "ooq8gZ1nKE5AqHuJYCjqEMkbYHgK2SDs9T2SZXDkJAZ196RKiBS", 
    "onqJPSCfU3BRzLesTnHHrbQn1FLAGpRCi7TRtxxiHbip9iHMWbU", 
    "onwg53FYDrfnnya3saqbrAEZUbnpTruMPTpqoKVuRazsf1Viwk5", 
    "onhFQfHozg6342FWHmneswFZRdoEuwvtfhmcpQQg1U9FsginVJv", 
    "opTn7nNd5vUBsex4a2bfR3RrZjUmkMeiAWEDttrrSEF3T1dGNZm", 
    "ooWkoM9xWNAd8EqbETpr1k5fEAuiQt598ugmLM54ZVNxjCbtGbp", 
    "oogDaA91FQsyYy3P9kYcJjS3ujmpHb94JGgjA6HpPSkPzgpB15H", 
    "ooaQLZaBXPXTe6aafhe96naZBGcoZi11FbzMhn385FseNEem2xF", 
    "opL6WmqQuWGyN9cNSmCwD8Ma6MV4Ts9So85WgcWp5Ky5tJkmLmh", 
    "ootzhwxQhEwnvrxzTeBWErHdC5m7BRzTfwDa2pSpaSkvRAwzU5K", 
    "oosyhGiANK4fZxc7hZ2j3NVUNiaTXQDPTKPK4GENmL8fNbqUsvB", 
    "ooLh1CUUtYveZTsG3GeA5rHmbsx9nQFTz9ynHGaEgJoC6dJYnti", 
    "oo5qw19WGmppfrnJZLyeRULUsAfjnffaQSLTqUHfLvKpXR3MqYd", 
    "onpj8MabGeVVHM4SkFewBuTzh7ZCzaS5nAHXzrzNCVtSEw2XzuX", 
    "ong2v5BqSaqatFHaxszrGydxBD12d5nURnXHHVwaijpvRow84Af", 
    "opW8UBt6o18DYbtoRX9zJQtzyD8jgU4y3siQpezuHUHCKFwNU7C", 
    "onojr4LVUpN9wCuLsBx3zTvAm7BFiaX6UuQPam6S2GgrQnD4c5Z", 
    "op2QbyAJAMc2XYEksdMKvEUgYgLV2gKUqbXahUjDUeruvixepqT", 
    "opWUQsURSggjD9fcSFvRipqfcCeWgZUt3sSNzNwEs59iu7uGdH3", 
    "onwfFre2mrardqbuM2UE8vJpF9H2hFWZorsPgNgak865KTJEF4k", 
    "opYvNapz6ofynufp1nkr1rRHwM3zS3Zt6ej3byMDPC5HR6hoB4a", 
    "ooRgJQGMHvbVtQkCpC1SoJRz4rCkWxoXFStBxARH5dAVYdnYKFn", 
    "oooFkkTvXw4geySWJbsnyGtv7uWSUCfZikqobG6VcFwXPqV41R9", 
    "oosNr1vxSqq2CJtBx6w89JMwBQykN1eCZjRRMhcVBBYQB1e13iq", 
    "opTmRk498HdVZ9QQxMPRVbrastMCZmYTgZS7A6p8xK2J9Sh8J26", 
    "ooB3dC8hsr9ZXNDVHD6KtAkDKEke2UxS8BfmijiT3eWDYynWiuh", 
    "onpQSBSjVeSx1zRpFhcwCGmhhawy2Za6ur18RoSqTFKcFEFWmpg"}, 
  "TransactionListDetails" -> 
  Association[
   "Endorsement" -> {
     "op6VomseCtH7rizEpty4e1kATAP2wZ95Zc2TnciUHgHDxsjAks4", 
      "opTjVuymKZuSgAvLq7QzfAn6pqgSJzFyYQx2ZYKA8J9AKYjGbUE", 
      "opNNDhSkp2j1s9MNyaH7nW4T8gREpPnDN7zPwnoxS2Q74EzRJYS", 
      "op9Sy24XKKJxwJ1UyBZ4didiyi6TtgDj2rMstCnYmPs9MLyCGra", 
      "oozW8QwRnGvde4yqf1P4xM99Nzb5o1tg4RHRJg3uVEWjYVG1Afw", 
      "op6EFngrBovURGURpKNsbz22r5bcRPaM4XbYCarStWG25X2kuJH", 
      "ooFkZjFM33UjXDLvkhkD1SNUguh8rnnLfmwFefS7YWNR2tCpfVA", 
      "onqdtnVexw5jsxy4P1FTbYRwBcNH1DrppjWgryCv32qqqw1Y7aP", 
      "ooCgPPZi75TbErNqUEpptUvx6mU9T8B1DCsaU4eJYtbrishZqGw", 
      "onudTXp25r5Zf2aZyMMKUAAFzqVQX24jwPNCN2TFPVQEA6hiEMk", 
      "op8eRJ5T3yMLDSzSbH4EA1VpA91VaMECCy6uGASfE1aNVWuu8tb", 
      "onpbU1aussshJatN8xfvqFWn3hNuDUZRD8SSem1XMrkcnnkRPwR", 
      "onwvab7jYybdAX8fmG7ntMXVgQoT1UXi8hHJDiuMu9DmHT7hsDV", 
      "ooPqN4ejaPjbuvn9aoGUzdj7Jb68Sp3CT4WV6ysvrvdEhSjw11u", 
      "oo9YcyDUZiJN5r6nTtr5uU2d6WgFuxby8zygjNbFUAkMbcq2Kkc", 
      "oojLDHmjFXpgcEdLrtu1ri5fkYyMLcxZVw4jxF2TZ3f7ELFkkwu", 
      "oo5znRzP43gSP5TKwaBHD96zkt4xw3QfRqEXFiXAEuUxTn9SDeL", 
      "ooqYjZ6boQBtVxRsBqrHxB9vmJRFkPAYysR2iaXigEQ6NepgDiV", 
      "ooETrujpf9SuB5ErLheg653puC7NEKA1DFLEZHttEBMVa7HaNJa", 
      "opAHbY3xtTUhekjv8Kgzvv6GS1uK3S4Arz5ygJiEVRZu8hSv7Vi", 
      "oodaSNWZfzyUHXa94pJ9vohwZS4FbEmtuZgMZnwf9WJ2mqkDcTW"}, 
    "Reveal" -> {
     "oouk2fBfhWPirfcNzdxXKxhDtnyMnvK65hD1MnHPApFuesFuuMt", 
      "opRcK6KBE1Y79GyGzmYsqRPZntxsV1A2gRK4iVZ91x573H1nTRp", 
      "opZVSQx9cVe4rxAv81eurea9GisjyFJc9DdKEiPSpgCB8aUtHG9", 
      "oogML3KCzAZZE1aaagcpXwfoa9R7zqdiiQHC9LT5j6ZcnsfY6P7"}, 
    "Delegation" -> {
     "oouk2fBfhWPirfcNzdxXKxhDtnyMnvK65hD1MnHPApFuesFuuMt", 
      "opRcK6KBE1Y79GyGzmYsqRPZntxsV1A2gRK4iVZ91x573H1nTRp", 
      "opZVSQx9cVe4rxAv81eurea9GisjyFJc9DdKEiPSpgCB8aUtHG9", 
      "onvdAawno4HEbLJhS1St7j3RFaCi7rDZSeAzC1DM7Cafs1EadMJ"}, 
    "Transaction" -> {
     "onqyJ3Cin5sxuWPvZgcVqXqBeTNFijkthcrz5bS4U8ATwhzodHK", 
      "op2hL6BVZg6y8zzQKQWzk5Bxs8Cr89QCSocFaYoNTVPvAXnQ4Hu", 
      "onijR1dKbGM1zR9dAbasxactqGQC4z6J6b4Uzrccy4vAnCD4Fn7", 
      "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
      "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
      "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
      "opTZK85vLQoU91TwLGvcCjFCKWeWbTxJEus4rYv2SgF97eHRZE5", 
      "onyUVr21aiaYCL8cQFSZ8S7iMtu3qKRmycWAMwrUELJ6Y8UWkr5", 
      "op2ZjLMAGz9N8uMwDF1eUt4SwPviLHvGEHLukB88vWVTkx4daT7", 
      "onpABZgtFEYCNQNJPDNX56M4UEbyekKY9NibBQw9x11KTqiaCbE", 
      "oogML3KCzAZZE1aaagcpXwfoa9R7zqdiiQHC9LT5j6ZcnsfY6P7", 
      "opPWXEj2p6MHCGfon4nZGVnG3zBXWY2CZtYVRRjVNDBvQPLxnUU", 
      "ooq8gZ1nKE5AqHuJYCjqEMkbYHgK2SDs9T2SZXDkJAZ196RKiBS", 
      "onqJPSCfU3BRzLesTnHHrbQn1FLAGpRCi7TRtxxiHbip9iHMWbU", 
      "onwg53FYDrfnnya3saqbrAEZUbnpTruMPTpqoKVuRazsf1Viwk5", 
      "onhFQfHozg6342FWHmneswFZRdoEuwvtfhmcpQQg1U9FsginVJv", 
      "opTn7nNd5vUBsex4a2bfR3RrZjUmkMeiAWEDttrrSEF3T1dGNZm", 
      "ooWkoM9xWNAd8EqbETpr1k5fEAuiQt598ugmLM54ZVNxjCbtGbp", 
      "oogDaA91FQsyYy3P9kYcJjS3ujmpHb94JGgjA6HpPSkPzgpB15H", 
      "ooaQLZaBXPXTe6aafhe96naZBGcoZi11FbzMhn385FseNEem2xF", 
      "opL6WmqQuWGyN9cNSmCwD8Ma6MV4Ts9So85WgcWp5Ky5tJkmLmh", 
      "ootzhwxQhEwnvrxzTeBWErHdC5m7BRzTfwDa2pSpaSkvRAwzU5K", 
      "oosyhGiANK4fZxc7hZ2j3NVUNiaTXQDPTKPK4GENmL8fNbqUsvB", 
      "ooLh1CUUtYveZTsG3GeA5rHmbsx9nQFTz9ynHGaEgJoC6dJYnti", 
      "oo5qw19WGmppfrnJZLyeRULUsAfjnffaQSLTqUHfLvKpXR3MqYd", 
      "onpj8MabGeVVHM4SkFewBuTzh7ZCzaS5nAHXzrzNCVtSEw2XzuX", 
      "ong2v5BqSaqatFHaxszrGydxBD12d5nURnXHHVwaijpvRow84Af", 
      "opW8UBt6o18DYbtoRX9zJQtzyD8jgU4y3siQpezuHUHCKFwNU7C", 
      "onojr4LVUpN9wCuLsBx3zTvAm7BFiaX6UuQPam6S2GgrQnD4c5Z", 
      "op2QbyAJAMc2XYEksdMKvEUgYgLV2gKUqbXahUjDUeruvixepqT", 
      "opWUQsURSggjD9fcSFvRipqfcCeWgZUt3sSNzNwEs59iu7uGdH3", 
      "onwfFre2mrardqbuM2UE8vJpF9H2hFWZorsPgNgak865KTJEF4k", 
      "opYvNapz6ofynufp1nkr1rRHwM3zS3Zt6ej3byMDPC5HR6hoB4a", 
      "ooRgJQGMHvbVtQkCpC1SoJRz4rCkWxoXFStBxARH5dAVYdnYKFn", 
      "oooFkkTvXw4geySWJbsnyGtv7uWSUCfZikqobG6VcFwXPqV41R9", 
      "oosNr1vxSqq2CJtBx6w89JMwBQykN1eCZjRRMhcVBBYQB1e13iq", 
      "opTmRk498HdVZ9QQxMPRVbrastMCZmYTgZS7A6p8xK2J9Sh8J26", 
      "ooB3dC8hsr9ZXNDVHD6KtAkDKEke2UxS8BfmijiT3eWDYynWiuh", 
      "onpQSBSjVeSx1zRpFhcwCGmhhawy2Za6ur18RoSqTFKcFEFWmpg"}]]|>

In addition to doing blockchain transactions and blockchain analytics with Wolfram Language, we’re also doing more and more with computational contracts—for which the full-scale computational language character of the Wolfram Language gives unique opportunities (an example being the creation of “oracles” based on our computational knowledge about the world).

In Version 12.1 we introduced ExternalStorageObject, initially supporting IPFS and Dropbox. In Version 12.3 we’ve added support for Amazon S3 (and, yes, you can store and retrieve a whole bucket of files at a time):

&#10005

ExternalStorageUpload["ExampleData/spikey2.png", "wolfram-bucket", 
 ExternalStorageBase -> "AmazonS3"]

A necessary step in all sorts of external interactions is authentication. And in Version 12.3 we’ve added support for OAuth 2.0 workflows. You create a SecuredAuthenticationKey:

&#10005

SecuredAuthenticationKey[<|"Name" -> "Reddit",
  "OAuthType" -> "ThreeLegged",
  "OAuthVersion" -> "2.0",
  "ConsumerKey" -> "" (*Your key here*), 
  "ConsumerSecret" -> "" (*Your key here*), "ResponseType" -> "code", 
  "Scopes" -> {"read"}, "ScopeDelimiter" -> " ", 
  "VerifierInputFunction" -> "WolframConnectorChannel",
  "AccessTokenURL" -> "https://www.reddit.com/api/v1/access_token",
  "UserAuthorizationURL" -> 
   "https://www.reddit.com/api/v1/authorize",
  "AdditionalParameters" -> <|
    "AuthorizationRequest" -> {"duration" -> "permanent"}|>
  |>]

Then you can make a request using this key:

&#10005

URLRead["https://oauth.reddit.com/api/search_subreddits" , 
 Authentication -> %]

You’ll get a browser window that asks you to log in with your account—and then you’ll be off and running.

For many common external services, we have “pre-packaged” ServiceConnect connections. Often these require authentication. And for OAuth-based APIs (like Reddit or Twitter) we have our WolframConnector app that brokers the external part of the authentication. A new feature of Version 12.3 is that you can also use your own external app to broker that authentication, so you’re not limited by the arrangements made with the external service for the WolframConnector app.

Under the hood for everything we’re talking about here is cryptography. And in Version 12.3 we’ve added some new cryptographic capabilities; in particular we now have support for all elliptic curves in the NIST Digital Signature FIPS 186-4 standard, as well as for Edwards curves that will be part of FIPS 186-5.

We’ve packaged all of this to make it very easy to create blockchain wallets, sign transactions, and encode data for blockchains:

&#10005

BlockchainKeyEncode[PublicKey[
Association[
  "Type" -> "EdwardsCurve", "CurveName" -> "ed25519", 
   "PublicByteArray" -> 
   ByteArray[{129, 57, 198, 230, 91, 48, 63, 133, 232, 63, 173, 17, 
     49, 237, 190, 143, 151, 108, 127, 202, 73, 93, 64, 14, 198, 177, 
     194, 15, 13, 79, 120, 246}], 
   "PublicCurvePoint" -> {
    299335060271590132066951334928298030649197201001541795411746200767\
72068584535, 
     53585483370699320092407628906864478900713122887718404470323110058\
487397628289}]], "Address", BlockchainBase -> "Tezos"]

&#10005

BlockchainAddressData[%, "DelegateData", BlockchainBase -> "Tezos"]

And Now … NFTs! (December 2021)

One of the things that’s happened in the world since the release of Version 12.3 is the mainstreaming of the idea of NFTs. We’ve actually had tools for several years for supporting NFTs—and tokens in general—on blockchains. But in Version 13.0 we’ve added more streamlined NFT tools, particularly in the context of our connection to the Cardano blockchain.

The basic idea of an NFT (“non-fungible token”) is to have a unique token that can be transferred between users but not replicated. It’s like a coin, but every NFT can be unique. The blockchain provides a permanent ledger of who owns what NFT. When you transfer an NFT what you’re doing is just adding something to the blockchain to record that transaction.

What can NFTs be used for? Lots of things. For example, we issued “NFT certificates” for people who “graduated” from our Summer School and Summer Camp this year. We also issued NFTs to record ownership for some cellular automaton artworks we created in a livestream. And in general NFTs can be used as permanent records for anything: ownership, credentials or just a commemoration of an achievement or event.

In a typical case, there’s a small “payload” for the NFT that goes directly on the blockchain. If there are larger assets—like images—these will get stored on some distributed storage system like IPFS, and the payload on the blockchain will contain a pointer to them.

Here’s an example that uses several of our blockchain functions—as well as the new connection to the Cardano blockchain—to retrieve from IPFS the image associated with an NFT that we minted a few weeks ago:

How can you mint such an NFT yourself? The Wolfram Language has the tools to do it. ResourceFunction["MintNFT"] in the Wolfram Function Repository provides one common workflow (specifically for the CIP 25 Cardano NFT standard)—and there’ll be more coming.

The full story of blockchain below the “pure consumer” level is complicated and technical. But the Wolfram Language provides a uniquely streamlined way to handle it, based on symbolic representations of blockchain constructs, that can directly be manipulated using all the standard functions of the Wolfram Language. There are also many different blockchains, with different setups. But through lots of effort that we’ve made in the past few years, we’ve been able to create a uniform framework that interoperates between different blockchains while still allowing access to all of their special features. So now you just set a different BlockchainBase (Bitcoin, Ethereum, Cardano, Tezos, ARK, Bloxberg, …) and you’re ready to interact with a different blockchain.