Permission-based webRTC signalling

wemeetagainwemeetagain Member Posts: 30
edited February 2014 in Projects
WebRTC (http://www.webrtc.org/) basically allows for simple p2p audio, video, and data. The only non-p2p components are usually the initial configuration of the peers (using a server to signal to each peer network and session metadata) and sometimes an intermediary relay server for peers behind restrictive NATs.

Ethereum contracts could act as a means of restricted-access p2p session initialization for WebRTC. One contract is a key-value storage linking ethereum addresses to public keys. Another is a nameserver/key-value storage that stores an ethereum address as the key and WebRTC session metadata encrypted with various other public keys as a list as the value. Perhaps there could even be a third contract that linked an ethereum address to a list of other ethereum addresses or public keys. Of course you need logic to be able to only allow the address holder to edit his key storage. And logic to delete metadata from keys for which you no longer want to provide the session data.

What you get from all this? A completely decentralized mechanism for letting 'friends' connect with mutual 'friends' via WebRTC.

How would it work? So the first contract lets a user link a public key to an 'identity'. When a user would set up an account, they'd send a transaction to the contract with a public key (or keys) as data alongside the transaction. The contract logic would store the keys under that address (so that friends can store data that is only visible to that user).

The second contract stores the signalling information needed to connect via WebRTC. Whenever the user went online/had their networking info change, they would send a transaction with the necessary session metadata needed to connect to them via WebRTC. The contract logic would lookup the keys from the third contract and store the encrypted forms of the session metadata under that address.

The third contract stored the 'friend list' of the user. The user could send a transaction signalling to add or delete addresses. The contract logic would add or delete addresses from that address' storage space.

So after the user has updated his session metadata, the user can search through the friend list of the third contract and lookup the session metadata on the second contract for each one found. Since the user owns the private key, the one of the metadatas from each entry can be decrypted and the user can then attempt to connect to each one.

If a friend does the same, then the user will be able to connect with the friend.

Of course, once connected, you'd want to do some sort of handshake with the keys to make sure the connection is legit, but there you have it.

The first and third contracts can be reused for other applications, as well.

I'm sure this could be better optimized/interoperble with other ethereum nameservers... open to all the ideas
Post edited by wemeetagain on

Comments

  • wemeetagainwemeetagain Member Posts: 30
    Ok, so thinking about it a bit more, I figure the logic should be a little different.

    Contract 1: go from name -> address. It should let you swap out the current address at that slot for another address, whether by trading your username to someone else, or wanting to use a new address. Note: this is mainly for the convenience of mapping a human-readable username to a less-human-readable ethereum address

    Contract 2: maps address -> identity contract. This should let the address owner enter the address of a standardized identity contract. It can be swappable so as to allow the address holder to change identity contracts if necessary.

    Contract 3: stores a public key (to be linked with the address in contract 2), as well as the webRTC session/network metadata (or generally any data), encrypted with the public key of each 'friend address', stored at the address of the friend

    here's the code (and Gist: https://gist.github.com/WeMeetAgain/9382663):

    // contract 1 // convenience nameserver // name -> address // address -> name // [name, newOwnerAddress (optional)] // only one name allowed per address // newOwnerAddress will only be applicable if the name is already claimed // if the transaction fee isn't enough to run the contract, stop if tx.value < 100 * block.basefee: stop // if the name is invalid, stop if tx.data[0] < 100: stop // if the name has already been claimed if contract.storage[tx.data[0]]: // if the sender isn't the current owner, stop if contract.storage[tx.data[0]] != tx.sender: stop // if the newOwnerAddress is invalid, stop if tx.data[1] < 100: stop // set new owner contract.storage[tx.sender] = 0 contract.storage[tx.data[0]] = tx.data[1] // the name has not been claimed else: //if the sending address already has a name, stop if contract.storage[tx.sender]: stop // set name owner as sending address contract.storage[tx.sender] = tx.data[0] contract.storage[tx.data[0]] = tx.sender // contract 2 // address -> contract address // [contractAddress] -- contractAddress is the address of the contract to link to // if the transaction fee isn't enough to run the contract, stop if tx.value < 100 * block.basefee: stop contract.storage[tx.sender] = tx.data[0] // contract 3 // id contract // [0,publicKey] -- add/change public key // [1,addr0,data0,addr1,data1,...,addrN,dataN] -- set each address with its corresponding data // [2] -- suicide // if the transaction fee isn't enough to run the contract, stop if tx.value < 100 * block.basefee: stop // if the sender is not the contract creator, stop if tx.sender != CONTRACTCREATOR: stop // if this is a 'set public key' command, set public key if tx.data[0] == 0: contract.storage[500] = tx.data[1] // if this is a 'set data' command elif tx.data[0] == 1: i = 1 // for each entry, if the entry isn't invalid, store the entry's data while i < tx.datan: if tx.data[i] <= 500: contract.storage[tx.data[i]] = tx.data[i+1] i = i + 2 // if this is a 'suicide' command, suicide elif tx.data[0] == 2: suicide(CONTRACTCREATOR)
  • wemeetagainwemeetagain Member Posts: 30
    another gist: https://gist.github.com/WeMeetAgain/9457099

    Imagine that the id contract stores webRTC connection data

    And imagine that a topicID is a geographic coordinate id.

    And imagine that peers only connect to addresses->contracts->connection info from peers in their geoID list.

    You've got yourself a system for geographically close peers to be able to connect p2p, securely.

    Notice that the id contract and name<->address contract can be reused in both this gist, and the last one.

    I imagine it wouldn't be too hard to make many different contracts that connect peers in many different ways. (I only really showed one-on-one and id->peer group based methods) These connection patterns could be swapped out depending on the connection needs of the user at the time.

    It wouldn't be too hard to imagine more complex id contracts that included multiple different connection possibilities, allowing for alternate connections (these could be used in different ways: trusted storage, trusted/untrusted relay servers).

    Why does all this matter?

    If you can solve the problem of how to connect peers (securely), you remove the main problem of connecting p2p, which was: trusting some server to set things up.

    Using a method like this, you effectively have fully decentralized, p2p connections that follow programmable. Think private networks, without manually bootstrapping the network.

    Another way of looking at this sort of problem space would be to think of the swappable linking contracts as trustless app-specific DNS servers, but that allow for more complex rules.

    So why use ethereum for this? And not namecoin, etc?

    The reason, for me, would be because its possible to create a whole web of contracts that link people in different ways, and create new ways(contracts) very simply. If there exist multiple different uses for ethereum, and with sharing of info between uses(ie, sharing modular contracts), it seems like it makes sense to go with ethereum. Beyond that, the users can/could configure different nameservers/intermediate logic, and this is all done without permission from anyone, and at a low cost.

    tl;dr: I think ethereum is useful for creating/sharing connections/relationships
  • wemeetagainwemeetagain Member Posts: 30
    Upon actually doing research on webrtc, it looks like there is no way to condense the necessary webrtc metadata into a single payload. Peers also need to know which peers are trying to connect to it, so it can connect/deny. Its beginning to look unlikely that ethereum is the proper medium for signalling, because it would take multiple blocks to actually complete a single peer connection.

    Another decentralized solution could be to use a DHT of webrtc-datachannel-connected peers that doubles as a webrtc signalling server, routing signalling information to the proper peer, allowing peers to essentially look up and dial other specific peers for different applications to connect via webrtc. This would be a great tool for developing p2p webapps.

    Ethereum would still have a role here, too. It could be used to determine which connections to allow, which connections to solicit, nameserver for peer id, etc.
  • miaozcmiaozc Member Posts: 3
    Hello! Have you pursued your idea further?
Sign In or Register to comment.