# MembraneProof Service API ###### tags: `Holo Architecture` `design doc` `membrane` `membraneproof` ## Context We need to provide simple mechanisms to make it easy for Holochain app devs and hApp providers to protect against Sybil attacks (i.e. creation of lots of sock-puppet nodes to overpower a DHT network). The easiest way to do this is to allow hApp publishers verify ownership of a phone number or email address and let them limit accounts per such identifiers. The launcher and HoloWeb SDK will be coded to enable service requests that generate membrane proofs based on user data, i.e. joining codes, secrets, etc. NOTE: this document is written as if Holo was going to provide the actual receiving end of the API and thus is a "turnkey" service for application providers so they don't have to. For beta (at least) we wont do that, but we DO want to provide the API so that application providers that want this service can setup up joining proof servers that can handle both immediate proofs or round-trip confirmation proofs for email/sms type options. ## Assumptions 1. The identifying key that has a clear owner in another "world" (i.e. email address, ETH key, DID) must be validated as under the control of the agent requesting it's use. For example email confirmation link clicked, Signing of some data with the ETH Key, etc 2. The membrane proof created will be self-proving, i.e. the genesis function can check a crypto-signature against a key that get gets from the DNA properties. There can be exceptions to this but it make validation much harder, and likely not possible during genesis. 3. There are different carriers that can be used to send joining requests that will be supported by the Launcher and by the Holo WebSdk - API specified https call to a holo-hosted service worker - sends email verification link... - sends sms cell phone verification (later?) - holochain notification service message - metamask signing request - provider/publisher hosted custom https Ajax solution In each case, the minimum needed is the AgentPubKey to be authorized, and proof of control of the outside key. Different apps may have their own additional data requirements (e.g. invitation code, proof of stake, proof of work, KYC / registration data, etc.) ## User Experience ### Holo Provider/publisher This is a case where we want smart defaults so they may never need to think about this. But we could provide a more "advanced" screen to override the default settings (for example, if you want the holo hosted screen to use Ethereum keys instead of email addresses) #### Turnkey Options - *Email Address:* [DEFAULT] verified by clickable link in email message, not persisted by the process - *Retained Email Address:* verified by clickable link in email message, stored in a provider controlled db (\$ premium) - *Mobile Number:* verified by text, not persisted by the process - *Retained Mobile Number:* verified by text, stored in a provider controlled db (\$ premium) - *Ethereum Key:* verified by metamask signing / key is visible in membrane proof for use within hApp #### Workflow Note: when using a turnkey option, we will generate a membrane authorizing key-pair, and store the private part in the cloudflare secrets DB for use by the cloudflare worker, and the public side gets put into the happ properties for use by the membrane proof. #### Developer Notes: We will provide libraries for developers to use in their validation routines to check the membrane proofs. ### Holo-hosted hApp User **Email:** - Email Address - Password - Pubkey is generated by chaperone and included in request sent to server for email message verification **Mobile Number:** - Cell Number - Password - Pubkey is generated by chaperone and included in request sent to server for text message verification **Crypto Key: (Ethereum, BTC, etc.)** - Outside key (e.g. Ethereum Pubkey) - Password - Pubkey is generated and sent to metamask for signing using `personal-sign` **User Workflow: (Email/Phone)** 1. Someone goes to web address of a holo hosted site, and gets to Sign Up page. 2. The fields on the page are presented according option configured in HHA by the app provider (default is email) 3. User enters email/phone/key & password, and clicks [Verify Email/Phone] 4. The fields are sent to a Cloudflare Service Worker which is specified in more detail below but basically - constructs a membrane proof using the necessary fields and signing it with the membrane-authorizor key - stores that membrane proof under a random 6 digit key in a KV store which another service worker will access - sends the 6 digit key to the specified email/phone 5. User enters 6 digit code they received by email/phone into a smart field which upon entering the 6th digit automatically retrieves the membrane proof from the service worker kv store and puts it into a HIDDEN FIELD. 6. Clicks [Send my Sign Up Credentials] 7. Chaperone sends all the goodies via Envoy so it has the proper membrane proofs to do the installation and genesis of the users source chains. **For Outside Cryptokeys** Initial steps are the same as above for email/phone. - Replace #3 Note: Metamask is required and it's presense should be detectable using JS. If present provide an action button [Sign via MetaMask], else provide a link to install metamask extension, based on their browser type, and the action button becomemail sendinges visible once extension is active. - Replace #4 with: Send a metamask `personal-sign` action to have the user sign their new Holochain AgentPubkey with their outside crypto key. - Replace #5 with: inject metamask data into hidden membrane proof field. Final steps are same as above for email/phone #### Service Worker for Sending Verification Code - Configured in Publisher Portal: hAppID, hAppName, Membrane-Authorizor private key, ReplyTo address? - Receives request containing hAppID, Email & AgentPubkey - Stores hash of email/phone in hApp's KV store for duplicate/Sybil detection - Signs the agent key using the the mebrane-auth key - Generates a random 6-digit key and stores signed key as a membrane proof in KV store under the compound key of hAppID + 6-digit code with a TTL of 48 hours. - Constructs an email/sms message from template containing instructions including hAppName, random 6-digit code, and maybe ReplyTo info? - Sends message NOTE: It would be feasible and maybe even smart, for us to later add a KV store which stores agent keys per happ/dna, so the service worker could detect/reject attempts at neighborhood attacks by having too many keys which are statistically tightly clustered. #### Service Worker for Retrieving Membrane Proof - Retrieves message from KV store using hAppID + 6 digit key - Returns membrane proof (Agent Pubkey signed by membrane-authkey) ### Holochain Launcher hApp User For Holochain/Launcher users where apps want to use email/phone for Sybil defense, we can make a field in the webhapp bundle format which has target URLs so that the launcher could provide a similar UI of sending phone/email and then retrieving membrane proof via 6-digit confirmation code. Then we can basically have the launcher follow the steps above (although user may need to manually cut/paste metamask signing inputs/outputs.) ## Important Note for Holochain Development We need to have Holochain accept multiple membrane proofs with each one identified using its DNA Name. We also need to enable cross DNA must-gets in validation so that we can have a single main membrane proof which can be confirmed as successful by other DNAs in hApp rather than requiring separate validation methods which could have some DNAs fail while other succeed (leaving the app in an awkward state). ## Workflow for Integrating hApp as an EVM sidechain Key Notes: - `JoiningSvc Client Library`: a Javascript npm library that can be used by the AppStore and other UIs that want to generate Membrane Proofs before installation. - `Joining Service`: A http REST API server for accepting `genMembraneProof` requests. In this case checking the request against an EVM chain. - `EVM Signing Service`: MetaMask or Wallet Connect ```sequence Participant Alice as Alice Participant AppStore Participant JoiningSvc Client Library as MPLib Participant KeyStore Participant EVM Signing Service as MetaMask Participant Joining Service as JoiningSvc Participant Holochain as HC Alice->AppStore: selectApp(hAppId) AppStore->MPLib: prepareInstall(hAppId) MPLib->KeyStore: createAgentKeyPair() KeyStore-->MPLib: AgentPubKey note over MPLib: for each DNA: \nget JoiningSvcUrl and\n MembraneProofType\n from DNA properties MPLib->MetaMask: bindAgent(AgentPubKey, DnaHash) note over MetaMask: "use EVM \nprivate key to sign" MetaMask-->MPLib: evmAuthPayload MPLib-> JoiningSvc: genMembraneProof(\nagentPubKey, evmAuthPayload) note over JoiningSvc: confirm EVM\nkey is allowed\n(checks block-explorer\n or local EVM node that\n key is DAO member) JoiningSvc-->MPLib: MembraneProof MPLib-->AppStore: Inject MembraneProofs\n into UI fields AppStore->HC: installApp(happID,[(DnaHash,MembraneProof)], seed) HC-->Alice: display installed app ```