--- tag: spec --- # Demo 1: messaging, contacts and recovery ## Problem statement Blockchains provide a synchronous messaging architecture; they create a total order on events, and as such allow the construction of a global state (under deterministic state transitions). With Metachains (see github) we expand this synchronous architecture, by allowing it to fork in to many parallel synchronous event-lines, and the ability to merge objects from these event-lines back into the main event-line or into sibling event-lines. This provides a solution to the verifier's dilemma for a PoW main chain, by compressing the useful work done on a metachain into a smaller consensus game played on the main chain. However, this alone is not sufficient to build powerful decentralised applications. Developers need an additional layer where asynchronous messages can be passed between instances of a software. In particularly applications relevant today no longer fit on a single computer, the data center has become the new base unit. Therefore the future of compution is reserved to owners of supercomputers and data centers, unless we can build applications that can fragment over the vast, untapped resources of devices users own at the edge of the internet. In this chapter we present the design for an asynchronous messaging layer on top of a synchronous backbone decentralised applications can use to orchestrate their services between devices owned by users at the edge of the network first, and allow services, including advanced computational graphs to be executed over nodes second. (continue) - the caching of messages when recipients aren't online - public-key exchange and rotation; - usability across multiple devices; - discovery // - photos/videos (within max limit of caching) (can be body + content key of your photo library; is it available?) ## Decentralised applications are user-centric Decentralised applications should be user-centric. Some may look at this statement and consider it a philosphical point. We want to briefly argue for it being a tautological requirement. Decentralised applications intend to organise useful outcomes over a large number of stakeholders. If the number of stakeholders would not be large, existing methods of organisation exist to direct outcomes, so most value is in building technology to enable large-group organisation. There is an edge-case where the group of users would not predominantly overlap with the group of stakeholders, but if the technology for large-group organisation is built, one can assume users -- all other things equal -- will prefer the instantiation where they benefit as user-stakeholders from the collective, over an instantiation where they are not able to contribute to the evolution of the organisation or share in the rewards. Therefore we deliberately build Mosaic as a framework and runtime for decentralised applications with user-siloed data and extended with computation over said data as a public good. ## Asynchronous message passing (improve) asynchronous message passing is the base functionality applications get from using the Mosaic framework. // thought: separate framework (the app code written with mosaic library) from runtime (the availability of nodes / network / honest majority guarantees) the decentralisation of the application is then derived from message passing between instances of the application executed on nodes; applications can be build on top of message-passing, crucially if a message-caching functionality allows for messages to be passed asyncronously between strings. ## Basic building blocks ### Strings and rings We want to construct an eventually-consistent database between a group of devices/machines. We build on ThreadsDB, and extend it with a contract representation of the shared thread. We build two types of such a contract, representing either a user entity, _string contract_, or a redundant group of nodes, _ring contract_, based on their availability requirement, and slightly different functionality [make less vague] 1. strings: a user can manage single-writer-logs for multiple devices on a string contract 2. rings: a node can join a ring contract to provide a service for an application ### Strings ```javascript= contract String { // all transactions are relayed bytes cidPrefix; uint256 nonce; // single nonce for all members mapping(address => address) members; // block number at which member deactivates mapping(address => uint256) deactivationNumber; mapping(address => bytes32) lastRecord; mapping(address => bytes32) previousLog; mapping(address => bytes) publicMultiaddresses; mapping(address => bytes32 /* PeerId */) peerIds; modifier onlyString() { require(msg.sender == address(this)); _; } constructor() { privateAddMember(msg.sender); } // set log head of single-writer-log to contract // stores last record and previous logNode // needed for account recovery of root logs of string members // payload contains RecordCID+PrevLogNodeCID // signature signs payload // see go-threads/cbor/record.go:L41 // replay attack is prevented with nonce from // executeTransaction by one of the members function setLogHead( bytes calldata _payload, bytes _signature ) onlyString { member = verifyMember(_payload, _r, _s, _v) // trim CID prefix from concat CID record+ CID prev record, prev = parse(_payload); ... } function addMember( address _newMember) onlyString {}; // also proceed if deactivation number < block.number; just store dn function deactivateMember( address _member, uint256 _deactivationNumber) onlyString {}; // metatx, break with EIP1077 (bc forces call on this) // follow GnosisSafe where applicable function executeTransaction( address _to, uint256 _value, bytes calldata _data, uint256 _gasPrice, uint256 _gasLimit, // refund cap?; or follow dataGas from Gnosis address _gasToken, address payable _refundReceiver, bytes calldata _signature // follow EIP1077 or our convention? ) external { // execute if (_gasPrice > 0) { handlePayment(...) } } } ``` ### Rings We detail specification of rings in [Rings](https://hackmd.io/@mosaicdao/BylE8bgqI). For demo1 we want to construct message caching; where a message is a single-writer-logNode ```javascript= contract Ring { // Storage /// Engine owning the ring. address owner; /// The ring's member count. uint256 memberCount; /// Sentinel pointer for marking start and end of the ring's members in the linked-list. const address SENTINEL_MEMBERS = address(0x1); /// Linked list of nodes. mapping(address => address) members; /// (Optional) public multiaddresses of members. mapping(address => string) publicMultiaddresses; /// (Optional) peerId // PeerId based (for now) on avatar public key; check pubkey -> address mapping(address => bytes32 /* PeerId */) peerIds; constructor() public { owner = msg.sender; } function enter(address _member) external onlyOwner; function exit(address _member) external onlyOwner; } ``` ### String-to-Ring "SLA" Ring members have a public multiaddress posted. Client can post JSONRPC to a ring member; ## Messaging - ring contract: sync across multiple your devices - use ring contract as pseudo-nomynous identifier? - research: DID (if it s relevant here) ### Initiating contact a. over QR code in person b. forwarded contact details over 3rd person Bobs' contact details: ```json { contract: <ring>, // gives PeerId of devices, try to establish direct //public encryption key: "0xabc", // would you store this on ring? //TTL: "end-date", } ``` #### Discovery service for dropping message-requests; and for discovery of dropped message-requests Approach: contract for managing global addressable conversation ### opt-in global username dir ### Conversation building a conversation as a new ThreadId each user may have multiple single-writer-logs for different PeerIds of different devices - key exchange - service key - read key 1. Alice initiates the conversation with Bob. Alice needs to encrypt the (threadId, sk, rk) for Bob. 2. where does Alice drop this initiation msg <=> where does Bob find new message requests / initiations 3. discovery-ring ### ## Contacts ### key-exchange Question? given Bob's ring contract, what is his public key ## Random questions / research - what s the entropy degradation of doubly using a seed for a signing / address public-private key; and then reusing the same seed for encryption (asymmetric) public key? - read signal paper / (telegram) - [Hopr project](https://www.hopr-project.org/index.php/Home) for obfuscating network packages (optional) - Status and Whisper: how do they manage caching / offline participants? - follow up on the active drafts of EIP1077 signing standards https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1077.md and https://eips.ethereum.org/EIPS/eip-1271; look to align later on, or make EIP - To RSV or bytes, that is the signature question - bytes calldata _signature // follow EIP1077 or our standard? - Gnosis Multisig has bytes - we ve used rsv thusfar - life... the answer is 42