Giter Club home page Giter Club logo

psibase's Introduction

psibase

β€’ Overview β€’ Demo πŸ–₯️ β€’ Docs πŸ““ β€’ Build πŸ› οΈ β€’ Run πŸš€ β€’ Contribute 🧬 β€’ Support πŸ“± β€’


Overview

Psibase is a powerful protocol that enables communities to come together to easily self-host web applications. This repository is an open source implementation of that protocol. Any psinode deployment comes with some default applications, some of which are mandatory and critical for the infrastructure to function properly, and others are optional sample user applications.

Primary packages included in this repository:

Package Description
psinode The psibase infrastructure node
psibase Command-line utility for interacting with psinode. Used primarily by scripts.
psidk The SDK used for developing web services

Demo deployment πŸ–₯️

A demonstration deployment is currently hosted at psibase.io to showcase what psibase infrastructure could look like for end users. The applications available on this demo are sample applications and are not intended to be used for a production deployment.

Technical docs πŸ““

Documentation is hosted on the docs app of our demo deployment.

Build from source πŸ› οΈ

We only officially support developing natively on Ubuntu 20.04 and Ubuntu 22.04, although any Linux distribution may work. If you use a distribution other than Ubuntu 20.04 or 22.04, ensure the versions of the dependencies you install are at least as high as they are in Ubuntu.

Some of our developers have very strong success with Ubuntu on WSL2, and also with Docker.

Environment setup

πŸ“¦ We maintain containerized development environments to simplify the development process. Developing within a container means the environment will automatically be set up for you. See the Psibase Contributor repository for instructions on how to build from source within a container.

The following is a list of dependencies you are required to install:

Package Minimum Version Description
autoconf 2.69 A tool for producing configure scripts for building, installing, and packaging software
binaryen 113 A compiler and toolchain infrastructure library for WebAssembly
boost 1.78 A collection of C++ libraries
clang + llvm 16 The LLVM compiler and toolchain for C/C++ and the libraries to interface with it
cmake 3.16.3 A build system generator that creates makefiles used for compilation
g++ 11 A GNU compiler for C++
libssl-dev 1.1.1 Development package for OpenSSL, enabling various cryptography andΒ secure network communication
libtool 2.4.6 Script that simplifies the process of creating and using shared libraries
make 4.3 Reads makefiles generated by cmake to build executables from source code
node 16.17.0 A JavaScript runtime
pkg-config 0.29.1 A helper tool used during compilation to provide correct compiler flags, and to locate and manage library dependencies
Rust toolchain 1.78 Develop programs in Rust. Use cargo to install cargo-component, mdbook, mdbook-linkcheck, mdbook-mermaid, mdbook-pagetoc, sccache, and wasm-pack
Wasi SDK 20.0 A development toolchain for building WebAssembly programs that target the WebAssembly System Interface (WASI)
zstd 1.4.4 Command-line utility that implements the Zstandard file compression algorithm

Other notes:

  • Add the paths to node, npm, yarn, cargo, and wasm-opt into your PATH environment variable.
  • Set the WASI_SDK_PREFIX environment variable before building to the root of your llvm installation (e.g. /usr/lib/llvm-16). Alternatively, set this variable during the build using the CMake flag -DWASI_SDK_PREFIX=.....
  • Add the following targets to rust: wasm32-wasi, wasm32-unknown-unknown

πŸ” You can reference either the Ubuntu 20.04 dockerfile or the Ubuntu 22.04 dockerfile for an example on how an environment could be set up.

Build

After your environment is set up, then you should be able to use the following build instructions:

git submodule update --init --recursive
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=psidk ..
make -j $(nproc)
ctest -j $(nproc)
make install

The built product lives in CMAKE_INSTALL_PREFIX ($CMAKE_BINARY_DIR/psidk in the above example).

Build flags

The following are some of the common/useful build flags you can use to configure CMake that modify the build. Open the build directory and run cmake -LH to view a list of all options.

Flag Example Values Description
BUILD_DEBUG_WASM yes,no Build debug wasms (Needed for using the debugger)
CMAKE_BUILD_TYPE Debug,Release Determines level of optimization for the native programs
CMAKE_EXPORT_COMPILE_COMMANDS yes,no Tell CMake to generate compile_commands.json, used by various tools (e.g. clang format intellisense)
CMAKE_INSTALL_PREFIX psidk Binary install location.

Running psibase infrastructure πŸš€

πŸ” We currently do not provide an ARM binary or docker image. If your device uses an ARM chip, you should build psinode (or its docker image) yourself.

To run psinode, you can either build from source as described above, or you can install prebuilt binaries through one of the following two methods:

  1. Installing a binary release, the latest of which can be found on our Releases page. We provide binary packages for both Ubuntu 20.04 and Ubuntu 22.04.
  2. Installing our psinode Docker Image.

To execute psinode from the docker image, you can use the following docker command (make sure to specify the VERSION you want to run):

docker run --rm -p 8080:8080 -p 3000:3000 -p 9090:9090 ghcr.io/gofractally/psinode:VERSION

Run psinode with --help to learn about the various options, or consult our technical docs.

Contribute 🧬

If you're interested in developing next-generation web application development & deployment infrastructure, welcome aboard! Come hang out in the community telegram channel to learn how best to contribute.

Alternatively, fork the project and do whatever you want with it!

MacOS 🍏

If you have a Mac (including Apple Silicon), you can use an Ubuntu 22.04 VM or Docker container. We do not host ARM variants of our docker images on our GitHub container registry. Therefore if you would like to use either the psibase-builder-ubuntu-2204 or psibase-contributor on your Apple Silicon Mac, you should pull the image-builders repo and build the images yourself.

Support πŸ“±

Some contributors to this repo hang out in this telegram channel. That's probably the best place to ask questions and get support.

psibase's People

Contributors

brandonfancher avatar bytemaster avatar conr2d avatar cool-ant avatar greenbusdriver avatar james-mart avatar omahs avatar sparkplug0025 avatar swatanabe avatar tbfleming avatar valzav avatar velua avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

psibase's Issues

Account invite system: Create invite & link

After someone attempts to generate an invite link, and after we check that the account-sys applet is in the same application group as the invite-sys applet, then we need to actually:

  • Generate the link
  • Store the invite object on chain.
  • Display it to the user

Multisig auth service

There are various actions in the fractally process that require multisig support.

  • Council defining system parameters
  • Teams modifying their membership
  • Council approving petitions (for eviction, and other actions)
  • etc

Develop multisig auth service

Psitest - Make more configurable

It should be simpler to add additional command line flags to change the behavior of psitest.
I will make it more configurable, and start by adding a flag to control whether it prints transaction times.

Fractally election service

Brief description

Election mechanic allows members of a fractal to submit their votes in weekly meetings to a psibase service

Dependencies

  • The token used for the fractal

Responsibilities

  • Unlocks automatically on time for consensus attestation
  • Stores winner information
  • Distributes funds

much more comprehensive spec needed

One-time contract initialization (security / dev-experience idea)

Background

A fairly common pattern is for contract authors to require some one-time initialization on their contract before the contract should be used. To achieve this, authors will add an init action which performs the configuration and sets a flag in the database. Every other action that depends on the initialization should remember to assert that the initialization happened.

Opportunity

Setting up the database flag, the init action, and asserting on the flag is all boiler plate that must be done for each contract. Therefore we could improve developer experience, and enhance security (negate risk of forgetting to assert), if we had a system people could use to achieve this.

Implementation

This is just one possible implementation. If a contract class has a specially-named function called initialize(), then our dispatcher could modify its behavior in the following ways:

  1. If initialize is called, it calls initialize on the contract base class instead of the child class, which sets an init flag in a standardized db row, then forwards the call to initialize to the child class for performing the actual init.
  2. Before dispatching every other action call, it asks the base contract class if the initialized flag is set

Conclusion

This would be an optional mechanism to help make writing contracts faster, and help with security by eliminating the possibility that a developer forgets to assert on the init flag.

Reference symbol contract

Initial version

Capabilities

The symbol contract allows people to create symbols (essentially buying them from the network), list them for sale on a public market, and unlist or buy them from the market.

The symbol contract is coupled to the tokens contract such that a symbol owner (who also owns a token) can transfer the symbol to the token contract, and then call an action on the token contract to permanently map that symbol to their token. The NFT that represents the transfer rights of the symbol is burned by the token contract when this mapping takes place.

Symbol pricing algorithm

Before creating a symbol, a user must credit the symbol contract enough funds to cover the creation of their new symbol. The cost of a symbol starts out at an arbitrary number, and adjusts every 24 hours according to the following algorithm:

if (number of symbols created in the last 24 hours > 24)
    cost = cost * 1.05
else if (number of symbols created in the last 24 hours < 24)
    cost = cost * 0.95

In this way, the cost of symbols will adjust according to market forces to target a rate of one new symbol created per hour. Symbols of different character length are priced independently.

Future version

Future version will allow additional administration functions, such as the ability to

  • update the symbol pricing rate of increase/decrease
  • for each symbol length, update the floor price and the target number created per day

Homepage - App directory

Introduction

Update the app directory on the home page to allow app developers to register their own app information for it to show up on the directory.

Metadata should at least include:

  • Name
  • Icon
  • Short description
  • Long description

Furthermore, add a search bar for users to search the apps in the directory.

Tasks

SIMD for WASM

This is probably the single biggest improvement for crypto functions and would provide a big differentiator.

Speed up applet load times

There's noticeable delays in loading applets. Very brief analysis shows that the same resources are being requested from servers multiple times. This should be avoided.

Event Subsystem

  1. Interblockchain Communication - Some events need to create merkle proofs
    • should be readable by contracts for a limited period of time
        addmerk( data ) {
                  auto seq = gseq++;
                 sha( seq, contract, data ). /// subjectively log data for wasm plugins to leverage
                 return seq;
        }
  1. Inter-contract communication - Some events need easy reference by other contracts (no merk proof required)

    • JUST THE DB API
    • should be readable by contracts for a limited period of time
    • events written to their own table, observers can query this table for updates.
    • if I want merkel proofs then I also call a native call with a hash
  2. UI communication - Some events don't need any proofs, but are still useful for queries

    • DB - Write-only, read never in contract, read from query
      put, remove - can be NOOP on some nodes...
      - mutable subjective queries that can also write (node operators only, because it is on main thread)

Transaction Dispatch Contract (priv contract)

Takes a blob containing a bunch of actions, authenticates them, then sync call with override sender permission.

Note: cannot dispatch an action to a contract without code.

      struct action {
               unit32_t     sender
               uint32_t     contract;
               bytes           data;
      }
      using claim = { proof_contract, vector<char>};

      struct transaction {
              tapos
              expire 
              vector<actions> actions;
              vector<claims>   claims;
      }

Example Transfer:

      transaction = {
             actions [
                     {   sender: user,
                         contract: tokens,
                        bytes:  = variant < transfer, ... > 
                                  function_num = transfer = 0,
                                  { from, to, amount, memo, ...}
                        }
                   }
             ]
      } 

Unit tests can just use action wrappers.... except, they need sender-override capability on action wrappers.

Applet infrastructure: Ability to execute operations

To execute operations, an applet needs an API to define and submit them.

Operations contain operations, or other actions.
Core needs to do a depth-first traversal of the operation and add all actions into a transaction object.
Then the user's specified auth contract is loaded in an iFrame, asked to sign the transaction.

For MVP, no need to ask for permission from each applet. All applets are assumed to be part of the same application group.

Then core submits the signed transaction to the chain.

Add context-free validation on action parameter

Add infrastructure such that custom objects receive a call like:
static void fracpack_validate(CustomType param)

Which allows them to do custom context-free validation, such as that a number is within bounds, etc.
That allows checking for parameter validity to be in one place, rather than spread among many actions, increasing contract security.

Add hooks for custom token behavior

Description

Token creators shall be able to publish contracts that customize the behavior of their tokens.

Implementation

The token contract shall allow holders of the token issuer nft to register custom contracts with their token. If a token has a registered contract, then actions with specific names will be called on the registered contract to facilitate custom behavior.

More details needed about what the hooks are and what kinds of behavior is customizable.

Database Native Calls

key {
uint32_t account/contract;
char[] userdata;
}

        kv_get( did, key ) => size  or -1 for non-existing
        kv_put( did, key, value)
        kv_greater_than( did, key );
        kv_greater_equal( did, key );
        kv_less_than( did, key );
        kv_remove( did, key ); 
        get_result( char* buffer, size ); /// general API for any call that returns something other than an int
        get_current_action(...) /// called by dispatcher which saves the account / sender /etc

Integrate invite system with resource model

Goal

Create a straightforward flow to allow users to invite new users to the blockchain and pay enough to give the user some initial resources and a premium name.

Design

As a user interacts with the chain, they consume CPU. Of the network tokens used to purchase that consumed CPU, 80% shall be burned, 20% shall flow into back to the user into a balance that can only be used to invite new users. This balance can be called "invite credits."

At any time, an account may interact with the Invite applet to create an "invite" for a dynamically calculated cost. The cost of the invite is 20% greater than the sum of the following on-chain metrics:

  • The current cost of the storage for a new account
  • The current cost for a premium name

An invite is an object that stores:

  • The user that invited the new member
  • The app that invited the new member (if a specific app was instrumental in facilitating the creation of the invite link)
  • The invite credits

This creates a unique link that the inviter may share with an invitee. After the invitee clicks the link, they may create their account, choosing between a basic name or a premium name, and any leftover funds get allocated into the new account's CPU budget.

As the new user users the blockchain, the network tokens used to purchase their consumed CPU will be directed to the regular liquid token balance of the inviter rather than the invitee's invite credit balance. This will continue until the inviter has been reimbursed 2x the cost of the invite, at which point the invitee's invite credits will start accumulating normally.

Questions

  • Should invite links expire?
  • How should we handle when the invite credits no longer cover the cost of the account creation + premium name, or if there are no credits leftover to add to CPU budget?

Proposals

  • What if, instead of the 2x repayment, invitees pay 5% of the cpu-consumed network tokens to the inviter in perpetuity?

Design artifacts

image

Watchdog tool

Problem

Currently, every time a change is made to a js or html file that gets uploaded to the chain, the easiest method to see the update is to kill the chain, and restart a test file that configures a new test chain and re-reads/deploys the content from disk to the new chain. This is cumbersome, and a barrier to entry - Most front-end devs are used to hot reloading during development where updates to their files can be immediately reflected on a local web server.

Solution

For development experience, we should have a tool that watches specified files or folders for changes, and then uploads the modified files to a local test chain.

Ideally, there should be a websocket connection between the node/client to allow the node to tell the client to automatically update its view of the applet.

Add auth delegation contract

Accounts (the actual psibase::AccountNumber) shall own an NFT which represents the authority to sign for that account.
The auth delegation contract should also allow people to register another NFT as an authorized signer on their behalf when using a particular contract.

Needs much more detailed spec

Contracts - Give as/at syntax to a contract

Current Test Syntax

chain.as("alice"_a).at<NftSys>().mint();

"as" creates the user context, and "at" specifies the contract interface with which the caller is interacting.

Current Contract Syntax

actor<NftSys>(contract, NftSys::contract).mint();

Desired Contract syntax

at<NftSys>().mint();

...or if I wanted to sign as someone else, I could use:
as("alice"_a).at<NftSys>().mint();

Proposed Implementation

Use CRTP to give the contract base class access to the child contract name:

class MyContract : public psibase::Contract<MyContract>

Then the base class can provide the desired as/at syntax.

Drawback

Forces all contracts to pass themselves into the base class.

Synchronous calls benchmark report

I want to know expensive it is to make a synchronous call into another contract the first time (when a new execution context must be opened), vs subsequent times in the same transaction (reuses the existing execution context).

The answer may help contract authors decide how to design their interfaces, should they prioritize smaller, simple functions? Or more complex, monolithic functions?

Pay to key

Description

According to the wallet front-end mockup, we need the ability to send tokens to key, and the sender pays the fee to store the tokens. A key can then be converted to an account.

Implementation

The token contract shall understand that credits to a special account called "pubkey" are stored in a balance tied to the public key specified in the memo of the credit action.

When someone calls debit with the pubkey account listed as the sender, and a specific public key listed in the memo, then the debit action will succeed if the public key is in the transaction's claims, and will debit from the corresponding public key balance.

Extra details

  • transaction-sys needs a new action for contracts to fetch all claims
  • to confirm the public key is in the claims, simply look through all claims until the contract matches verifyec-sys and the content matches the public key.

Action Dispatcher

  1. Proxy Object on Caller Side (action wrappers)
  2. Dispatcher on Receiver Side
      class othercontract {
             flat<string> callme( flat<string> hello );
      };
      REFLECT( othercontract, (callme, p1, p2, p3)  )
     template<int funcnum, typename R, typename Params...>
     struct memberobject {
     }

     proxy {
          memberobject callme() { return membeobject<...>(contract) };
          flat<string> callme( flat<params...> )
     }
      proxy<othercontract> prox(accountnum, sendernum = currentcontract() );
      auto result = prox.callme( .... )

Priv Contacts for Unit Tests
proxy prox(contractnum, sendernum);

Block Signature System

       struct claim {
              hash                    contract; 
              vector<char>    data;
       }
       micro_op = variant< set_producers>

       struct block_header {
             uint32_t                          blocknum;
             uint64_t                          time_us;
             uint32_t                          notary // block producer
             sha                                    hash( trx_mroot, event_mroot );            
             vector<micro_ops>     ops;     /// set producer set, lib changed, ... 
       }

       struct signed_block_header {
             vector<proof>
       }

Move web assets onchain

React, React-DOM, and other packages that we currently dynamically pull in, should be deployed on-chain.

Make system token (PSI) untradeable by default

Untradeability is a pretty standard trait for a token to have, so it should be added to the base token contract as a property that a token can have.

When a token is untradeable, it:

  • Cannot be credit to anyone, except by the owner of the token issuer NFT. This allows untradeable tokens to still be distributed, but prevents anyone from trading them.

In the initialization of the token contract, the system token should be made untradeable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.