Frozen - amark/gun GitHub Wiki

A hash is a short yet unique "fingerprint" (see the cartoon explainers) of your data. It can be used as a name that is self-referencing to itself, frozen at some point in time. For instance, if the data were to change, then it would also get a new name.

This is useful, because it lets you verify that data has not been changed even if it is in a public place. And using SEA with GUN, it prevent peers from changing the data if some name/key combo of '#'+hash is used.

Note: This does not guarantee peers will keep the data saved though, they might expire it over time.

Here is a quick example of how to get started:

<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script>
var gun = Gun();

var data = "hello world";
var hash = await SEA.work(data, null, null, {name: "SHA-256"});

gun.get('#').get(hash).put(data);

gun.get('#').get(hash).once(console.log);
</script>

Later, try to do something like:

gun.get('#').get(hash).put("hi");

And you'll see an error that the hashes are not the same.

You can also make your data organized and searchable using RAD:

gun.get('#anything').get('2020-06-06-keyword#'+hash).put('hello world')

You should be able to mix & match this, for instance, creating an immutable inbox:

gun.get('notify@Alice/2020/1/1#').get(notificationHash)

This would let you send notifications to Alice that she could read that others cannot edit. If you do not want others to be able to read these notifications, you can encrypt them with a key pair.

Note: If you want it to be anonymous, you can generate a throw-away key pair.

Just remember, taking the hash is always the last operation. If you encrypt the message, you must take the hash of the encrypted message, not of the original message.

UPDATE: Immutable links to mutable user content

You may want your users to create immutable links to their private mutable nodes. Once there will be a nice chainable method for that, but for now you can use this

// Logged in user writes a message in his signed graph. Notice, it should be an object in order to have a soul
gun.user().get('messages').set({text:'hello'}).on(async data => {
    let soul = data._["#"]
    let hash = await SEA.work(soul, null, null,{name:'SHA-256'})
    gun.get('#messages').get(hash).put(soul)  // User puts a hashed soul of the message in a public content-addressed node
})
// Others can read the message later with the soul
gun.get('#messages').map().on(data=> {
    gun.get(data).once((d=>console.log(d))) // {text:'hello'} 
})

If you want to link just the text node in a user graph, you may store just the UUID of the message in a RAD indexable content-addressed list.

let message = 'hello world!'
let userPub = gun.user().is.pub
gun.user().get('messages').set(message).on(async (data,key)=> {
  let hash = await SEA.work(key,null,null,{name:'SHA-256'})
  gun.get('#messages').get(userPub+'#'+hash).put(key)
})
// then anyone can list messages of a particular userPub right from the private graph
gun.get('#messages').get({'.':{'*':userPub}}).map().once(data => {
 gun.user(userPub).get('messages').get(data).once(d=> {
   console.log(d) // 'hello world!', true
 })
})

Need help? Discuss this further on the chat and/or please update this wiki with new insights!

⚠️ **GitHub.com Fallback** ⚠️