{"action":"created","issue":{"url":"https://api.github.com/repos/ipfs/notes/issues/179","repository_url":"https://api.github.com/repos/ipfs/notes","labels_url":"https://api.github.com/repos/ipfs/notes/issues/179/labels{/name}","comments_url":"https://api.github.com/repos/ipfs/notes/issues/179/comments","events_url":"https://api.github.com/repos/ipfs/notes/issues/179/events","html_url":"https://github.com/ipfs/notes/issues/179","id":184595258,"number":179,"title":"A consensus interface for libp2p","user":{"login":"whyrusleeping","id":1243164,"avatar_url":"https://avatars.githubusercontent.com/u/1243164?v=3","gravatar_id":"","url":"https://api.github.com/users/whyrusleeping","html_url":"https://github.com/whyrusleeping","followers_url":"https://api.github.com/users/whyrusleeping/followers","following_url":"https://api.github.com/users/whyrusleeping/following{/other_user}","gists_url":"https://api.github.com/users/whyrusleeping/gists{/gist_id}","starred_url":"https://api.github.com/users/whyrusleeping/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whyrusleeping/subscriptions","organizations_url":"https://api.github.com/users/whyrusleeping/orgs","repos_url":"https://api.github.com/users/whyrusleeping/repos","events_url":"https://api.github.com/users/whyrusleeping/events{/privacy}","received_events_url":"https://api.github.com/users/whyrusleeping/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2016-10-22T00:15:44Z","updated_at":"2016-10-25T08:07:06Z","closed_at":null,"body":"@jbenet And I sat down and did some thinking about how to abstract consensus for use in libp2p and general ipfs applications.\r\n\r\nHere are my notes:\r\n\r\nWe decided to have two layers of the interface. The first layer of consensus is simply to agree on a single value across the cluster of nodes.\r\n\r\nThe interface for that looks roughly like:\r\n\r\n```go\r\ntype Consensus interface {\r\n    // GetCurrentState returns the current agreed upon state of the system\r\n    GetCurrentState() (Node, error)\r\n\r\n    // CommitState attempts to set the current state of the system. It returns\r\n    // the new state of the system if the call succeeds.\r\n    CommitState(Node) (Node, error)\r\n\r\n        // SetActor sets the underlying actor that will actually be performing the\r\n        // operations of setting and changing the state.\r\n    SetActor(Actor)                                                                                                                                                                                 \r\n}                                                                                                                                                                                                   \r\n                                                                                                                                                                                                    \r\ntype Actor interface {\r\n        // SetState attempts to set the state of the cluster to the state\r\n        // represented by the given Node\r\n        SetState(Node) (Node, error)\r\n}\r\n\r\n```\r\n\r\nAll this does is allow a set of actors to agree that a given node is the 'current state'.\r\nThis is a very simple interface, but its also a very powerful one. Most applications that use 'consensus' are using exactly and only this.\r\n\r\nBeyond that, we define another interface that maintains an Op log:\r\n\r\n```go\r\ntype Op interface {\r\n    ApplyTo(Node) (Node, error)\r\n}\r\n\r\ntype OpLogConsensus interface {\r\n    // CommitOp takes the current state and applies the given operation to it, then\r\n    // sets the new state as the clusters 'current' state.\r\n    CommitOp(Op) (Node, error)\r\n\r\n    SetActor(Actor)\r\n\r\n    // GetLogHead returns a node that represents the current state of the cluster\r\n    GetLogHead() (Node, error)\r\n\r\n        // Rollback rolls the state of the cluster back to the given node. The\r\n        // passed in node should be a node that was previously a state in the chain of\r\n        // states. Although some discussion will need to be had as to whether or not\r\n        // this is truly necessary\r\n        Rollback(Node) error\r\n}\r\n```\r\n\r\nNote: its not currently clear (to me) whether the `Actor` interface needs to\r\nchange to support the `Op`, or if the Op is applied to the state and then\r\n`SetState` is used to set the 'State' to a node that represents the state transition.\r\n\r\n\r\nHaving this log based consensus gives us a few really neat features:\r\n\r\n1. The ability to roll back state to some previous state. Since every operation used to generate the existing state of the cluster, we can at any point replay from the beginning the entire log up until the desired rollback point.\r\n\r\n2. Having a log allows us to easily and nicely build more advanced data structures on top of the generalized oplog consensus. For example, [orbit-db](https://github.com/haadcode/orbit-db) could be (almost) trivially modeled on top of such an interface.\r\n\r\n3. Somewhat obviously, but still worth mentioning, The availability of the op log allows peers to browse through the history of the clusters state."},"comment":{"url":"https://api.github.com/repos/ipfs/notes/issues/comments/255966168","html_url":"https://github.com/ipfs/notes/issues/179#issuecomment-255966168","issue_url":"https://api.github.com/repos/ipfs/notes/issues/179","id":255966168,"user":{"login":"hsanjuan","id":1027022,"avatar_url":"https://avatars.githubusercontent.com/u/1027022?v=3","gravatar_id":"","url":"https://api.github.com/users/hsanjuan","html_url":"https://github.com/hsanjuan","followers_url":"https://api.github.com/users/hsanjuan/followers","following_url":"https://api.github.com/users/hsanjuan/following{/other_user}","gists_url":"https://api.github.com/users/hsanjuan/gists{/gist_id}","starred_url":"https://api.github.com/users/hsanjuan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hsanjuan/subscriptions","organizations_url":"https://api.github.com/users/hsanjuan/orgs","repos_url":"https://api.github.com/users/hsanjuan/repos","events_url":"https://api.github.com/users/hsanjuan/events{/privacy}","received_events_url":"https://api.github.com/users/hsanjuan/received_events","type":"User","site_admin":false},"created_at":"2016-10-25T08:07:06Z","updated_at":"2016-10-25T08:07:06Z","body":"Yeah go ahead and rename @whyrusleeping, but perhaps it should be `State` since its a parameter for `CommitState` and a distributed-log `Entry` is just a particular case of State in the end.\r\n\r\n Also, note `state of the system` vs `state of the cluster`, probably should be the same thing."}}
{"actor":{"display_login":"hsanjuan"}}