SlateStore Protocol

I think transport channels should be in the slatepack address, I’ve once mentioned that on keybase and gave such example:

transport: {
  methods: {
    tor: <ed25519pubkey>,
    ...,
  },
  encryptionkey: <staticEd25519pubkey>
}

where the encryption key is somehow derived from the private key.
The qr code could contain the slatepack address itself, so like a wrapper for situations where scanning makes more sense - note that if we exchange this data through chat then text is probably easier

1 Like

I remember seeing it come by on keybase, I really like the idea!
If I remember correctly it was mentioned that for some technical reasons we cannot put much more information in the slatepack address.
Therefore I was thinking if we could put such information as you proposed in some larger wrapper, like a QR code, but it could also be part of a slatepack itself. For example when using the RSR flow you invite someone to pay a bill, and you provide multiple options for the sender to send the signed transaction so that the Receiver does not need to be online. E.g. the signed slatepack is emailed to him directly by the wallet in case the receiver is offline. Of-course it would be just as handy for SRS flow to provide this extra logic and these extra channels for receiving the signed transaction.

I think it matches what you proposed, having some sort of minimal logic in there to say, try transport method 1, if that fails, go to method 2, etc. Best to make it a generic minimal standard so we can introduce new methods and transport channels in the future without hassle.

I think ideally, Slatepack should know nothing about the transport. Let’s restructure your design a bit. Think of a slate as a message M. Now, instead of embedding the transport in M, you add a transport layer around it e.g.

{
  // How
  "transport": {
    "tor": {
       "addr": <ed25519pub>
    }
  },
  // What
  "data": M
}

The Slatepack now knows nothing about how it arrives at a destination. Building things in layers rather than adding features to the existing layer usually gives a cleaner design.
Given that slatepacks (mostly) include the other party’s public key, you could use this key to encrypt the transport message. The only difference is where the transport information lives. This also means you can change the transport protocols however you want without needing to create a new slatepack standard version.

1 Like

Make sense, we could call it an extended slatepack, slatepack wrapper, or a smart transaction script.
First field should be something to distinguish what it is or we should use something like magic bytes to indicate it is a transaction script. I think we can freely borrow ideas from for example PSBT which start with some magic bits that spell ‘psbt’ to help wallets distinguish it from transactions.

1 Like

The way I imagined it was that there is no need to explicitly specify the transport method. I would just add a field (maybe excess value? not sure how to do that) that proves the transaction has an extra reward when finalized.

Then we broadcast it like a regular transaction. Network nodes / miners recognize it is not yet valid and receiver signature is missing so they do not attempt to append it to next block. They can also verify that there is an excess ready to be claimed, so everyone signs it to claim it. Everyone has own copy with own signature of this reward. The first one who collects the receiver signature and appends to the next block wins the excess reward.

2 Likes

If everyone has a copy it will become a race, which might bring some problems. For example, a hundreds of nodes all contacting the receiver when he/she comes online. Now, you could sign everyone’s transaction and let them race, in which case miners will have to somehow randomly select which of these transaction to keep, or only sign a single one, in which case an attacker could block your transaction by being the first to contact you. Also the receiver could ‘cheat’ by signing and sending to a friend to give him the reward.

Anyhow, a lot of complexity, which can be solved by sending to a specific backup node which you specify yourself. E.g. a friend or community service provider. But the idea is intriguing, so definitely worth it to explore it more.

If the receiver signature is missing, then the sender (in SRS) can’t know if this will ever become valid at the moment they broadcast. This introduces some uncertainty about the transaction both for the party involved as well as everyone else. I’m not sure we should be broadcasting invalid transactions or accepting invalid ones in the mempool.

Good point. I agree it should not be mempool (although implementing a dedicated and distinct P2P protocol just for that seems like overkill). Maybe there is some known protocol that could be just grabbed and used for that.

I would like to emphasize just one thing: For each of those partial transactions there is a risk of never getting resolved, that is why for every node/miner it should be completely optional to agree to store and process them. This is also why an extra reward would be offered.

I think for any owner of such node/miner there should be a timeout parameter after which partial transaction is removed. Default something like 24h etc.

Sounds a bit to limited to me, 7 days would be better.
One problem is sharing your slate-address with everyone, which makes it impossible to make a race, since you do not want everyone to have it. Otherwise they could link outputs to your slate-address, making Dandelion useless, or even trace you by contacting you via multiple nodes on the tor network.

You could make the user select a random node that had the transaction with signed reward for him/herself, but that would make it easy to cheat, e.g. only send to a friend who has it buffered.
In any case, I think it would be safer to provide a specific backup provider, this makes it much harder to attack, since many users use different backup nodes, then if a single mempool or secondary mempool would be used.

We could also build such a system free without incentive, just community driven, a secondary mempool that is only run by nodes that willingly store these slate-packs. This can however, easily be spammed, unless we introduce some account system with a maximum number of slates each account can store.

If I understand correctly the flow of the current suggestion (where no miner is involved) is:
Alice -> Carol -> Bob -> Carol -> Alice
In that case the same could be achieved if all Carol did was simply facilitate the exchange of a regular (encrypted) slatepack transaction between Alice and Bob, basically a messaging app. (With the difference being that there won’t be an extra reward fee for Carol. However this could be solved in other ways, like a signup fee)

With that being said I still think that this process would be too convoluted and we need to find a simpler more elegant solution. My main gripe is the need for Alice to finalize the transaction as I feel that step is just unintuitive to the average user.

She clearly needs to sign for the transaction. Which is what happens in the unfortunately named finalize, along with publishing.

Well yes, but the sort of flow I’d like to have would be:
Alice -> Carol -> Alice then Carol -> Bob -> Carol
The naive implementation of this would not be trustless. But maybe someone can figure out a protocol that would make it trustless. How that would be done I do not know.

1 Like

Maybe Alice and Carol could form a tx of value: Carol fee + Bob payment. This transaction would be additionally blocked using an adaptor signature. Making it valid would require to find a tweak value to subtract from it, and tweak value could be derived from transaction between Carol and Bob?

Edit:

Or better. Alice and Carol make a shared output on chain with two outcomes:
(1) Carol made payment to Bob, no time lock but blocked using adaptor signature of valid payment between Carol and Bob
(2) Carol ignored the job, this one is locked until the deadline passed.

1 Like

Correct me if I am wrong, but a major reason for this idea is “messenger apps require you to reveal ypur identity”.

Wouldn’t it be easier to just use an anonymous or throwaway messenger service rather than creating this protocol?

This is one of the reasons, yes. More explanation under next quote.

You are right, it would be easier. Problem is every service requires someone to run it, pay for the bills etc. You never know how long it will be up. What I had in mind is ツ based service that accepts ツ as payments, this way as long as you are willing to pay fees in ツ you will get your slates stored until processed.

1 Like

Session and Status messengers are good ones to look into.

If you really want to pay for usage in Grin, Nostr is an interesting possibility because it leaves the economic side completely up to the node operator. The problem is that we don’t yet have payment proofs for Grin, right? So how do we prove to the node operator that a specific person has paid?

Very interesting suggestion! I like it!

We do have payment proofs. They have some limitations (only sender can generate such a proof and there is no way to embed any extra info in them) but for this purpose they would do.

Still, person receiving slatepacks via Nostr would need to be instructed to search for it over there. What I had in mind when I proposed this protocol is you just make a payment and agree for some fee for storage. Everything is done automatically by the network, no need to provide any special instructions to the receiver.

3 Likes

so the payment to the Node can just be an online transaction because the node will always be online. and the payment to your friend is stored via a NOSTR note.

So you’re making two nearly simultaneous fees (one slatepack and one interactive), yes?

Here is a nostr relay that charges per user account (not per note) GitHub - fiatjaf/expensive-relay: a nostr relay that requires a single registration payment per pubkey