amark / gun

An open source cybersecurity protocol for syncing decentralized graph data.
https://gun.eco/docs
Other
18.05k stars 1.16k forks source link

How to validate user data? #1228

Closed Osiris-Team closed 1 year ago

Osiris-Team commented 2 years ago

Let's say user A says 1+1=3 and adds 3 to the database, that result is obviously wrong so we would need some kind of logic to validate the data on a decentralized database.

Couldn't find this in the docs or issues. Is there something like this built-in gun?

I thought it could be done by having multiple users check the change in the database and then correct it after agreeing on the correct/valid value.

atordvairn commented 2 years ago

moderation like stuff?

atordvairn commented 2 years ago

you can't control public data in decentralised systems what you can do is to not to render them. ex: a post has more dislikes than likes, hide it.

Osiris-Team commented 2 years ago

Example for clarification: If I wanted to create a multiplayer game, where the coordinates x, y, z of each player are shared among each other, then each player would have to check if the new position of the other player is valid, based on the position the player had before and the maximum allowed movement. Otherwise, people just could fly around or run faster than others and teleport to different places.

Of course the majority of the players would have had to agree on the maximum allowed movement speed before starting the game.

atordvairn commented 2 years ago

hmmm, that's hard to take care of

the only thing that comes in my mind is to compare the before and after coordinates to validate..

Osiris-Team commented 2 years ago

Yeah then the question would be if all players have the latest last coordinates of one another. If one player has the last coordinate of another player, that actually is the last coordinate of 3 seconds ago, the validation will fail and the player thinks that the person teleported and will try to fix the value which would throw the other player back. So I would have to trust gun that the data is synchronized correctly.

Or add a limit of how often one player tries to change the other players' position. Idk. thats why Im asking ^^

trosel commented 2 years ago

You are discovering why smart contracts were created @Osiris-Team :)

Gun can only take you so far in terms of decentralized use cases. Eventually you do need something like smart contracts to coordinate.

But I don't think there is a smart contract system that works at speeds needed to run a real online game.

So what people would do most of the time is have the "contract" handled by a closed source game app and only let the game app update the Gun db (don't let the users update their own position)

Osiris-Team commented 2 years ago

Ok I hoped there would be something like that implemented in gun. Since data validation is kind of an important topic in a decentralized database I think. It would be cool to have to simply enable a validation method, and all the complicated stuff happens under the hood. Just throwing ideas around, have no clue how any of this works. @amark are there any plans in implementing something like this?

trosel commented 2 years ago

Since data validation is kind of an important topic in a decentralized database I think.

It's a question of use case more than capability. You can moderate content in Gun through various patterns. You can have different levels of permissions as well (contributor, editor, owner).

But the use case you described... I don't think that is possible in any decentralized system today. If you're open to hearing other possible solutions, there may be a different way of looking at the problem.

JohnYepthomi commented 1 year ago

@Osiris-Team Do you have any solution to this? Here's something I'm trying, let me know if you have a come to a better solution.

var Gun = require('gun');

function extractUserPayload(msg) {
    let payload = {};
    let fullPath = '';

    Object.keys(msg.put).forEach((key) => {
        fullPath = key;
    });

    payload = msg.put[fullPath];
    delete payload['_']

    console.log({ fullPath, payload });

    return { fullPath, payload };
}

Gun.on('opt', function (ctx) {
    if (ctx.once) {
        return
    }

    ctx.on('in', function (msg) {
        const to = this.to
        if (msg.put) {

            /* Get the user payload and do some validation.
               The validate() function below hasn't been implemented.
               You can use your own validation function that validates the extracted payload */
            const validated = validate(extractUserPayload(msg));

            /* call next() if its valid or ignore if not validated */
            if (validated) to.next(msg)
        }

    })
})

var gun = Gun({ web: config.server.listen(config.port), peers: config.peers });

console.log('Relay peer started on port ' + config.port + ' with /gun');
Osiris-Team commented 1 year ago

@JohnYepthomi thanks for sharing your code! No I didn't find any solution, but that's mostly because I didn't start the project I would require this in.

amark commented 1 year ago

@Osiris-Team you're correct. @trosel is correct that performance matters, but even then, you'd never want this on a smart contract (see later).

The way you described doing it is how to do it. GUN.state.is(node, key) will return the vector/timestamp of the update, so you use this when calculating time differentials. If state_a is at posX and then state_b is at posX+100000 then clearly it violates.

You do NOT want every peer in a network enforcing this logic, which is what smart contracts do, this is a terrible idea that does not scale. Your application is the p2p "smart contract", as only the peers running your app are the ones enforcing your app. So when your app logic sees an invalid update, don't render it!

Honest peers will see each other. Dishonest peers will vanish. Bonus mode: Show cheaters to only other cheaters, so they compete on cheating - a whole new meta game.

gartz commented 1 year ago

I believe the fix for this is to implement consensus protocol. The app must have a key that validates the consensus mechanism implementation and version, then when a new data a peer arrives, that consensus will validate the data, if the format and content is valid, it does persist and propagate. When invalid it discard, creating a “fork” in the network and isolating bad actors and old versions.

pretty much same as smart contracts and IPFS.

To control that the new DB should have authorship public key(s) that will be used to match consensus implementation. Therefore every consensus script needs to be serialized and signed, and the public key to validate that signature goes with the DB constructor options.

For example:

gun({consensus:[“xxx”]});

// where callback is a function that can be serialized and it’s code is signed by the private key that owns the public key of the consensus xxx const getRule = gun.contract(callback, signature);

const putRule = gun.contract(callback, signature);

gun.get(‘something’, getRule).put(dataObj, putRule);

Therefore let’s say that the put rule prevent data to be deleted at all, it can only be added to the dataObj. Once the peer sync this change it can validate the new dataObj and if fail the consensus execution, it ignores the change.

if a peer spam the change it can get banned from the peer, therefore removing bad actors from the network.

it doesn’t prevent bad consensus implementation, but, gives tools to devs to prevent someone to open the source code delete data and propagate the damage to the network. Or restrict who can do certain changes by requiring some kind of signature to create admin access, that kind of thing.

amark commented 1 year ago

Thanks for the extra ideas. There's about 30 different ways this could be implemented and is extremely specific to the app, so yeah the app should do this/define the rules. GUN let's you extend itself GUN.chain.contract = function(){ ... so challenge: Get 5 devs to all implement their own version of this, then test/play with each others, see which one is the best. Whoever wins we'll have it published as a gun module or if super popular, even pull it into this repo (if its not super bloated).

Gonna close, since pretty detailed answers have been provided, & trying to keep github issues relevant to current existing bugs.