Git Product home page Git Product logo

kunta-labs / africaos Goto Github PK

View Code? Open in Web Editor NEW
12.0 8.0 2.0 36.19 MB

A distributed, proposal-based, replicated state machine (RSM) written in pure Rust. AOS is a simple, blockchain protocol designed for customization.

Home Page: http://aos.kunta.io

License: GNU General Public License v3.0

Makefile 4.63% Rust 94.90% Dockerfile 0.47%
blockchain blockchain-technology blockchain-platform blockchain-network protocol distributed-computing distributed-systems decentralized decentralized-application cryptocurrency crypto pbft replicated-state-machine ethereum smart-contracts bitcoin libra tezos monero litecoin

africaos's Introduction

Africa Operating System (AfricaOS)

A simple, customizable, proposal-based, replicated state machine (RSM), inspired by pBFT (Practical Byzantine Fault Tolerance) written in pure Rust. We show how to setup an N-node network, of which accepts transactions. The transactions can execute arbitrary logic.

Status Type Status
Master Build Build Status
Development Build Build Status
Issues Issues
Last Commit Last commit
Docker Stars Docker Stars
Docker Pulls Docker Pulls
Docker Automated Docker Automated
Docker Build Docker Build
License License
Releases Releases
Latest Release Latest release
Top Language Top language
Code Size Code size in bytes
Chat Discord

White paper

Read here: https://arxiv.org/abs/2003.10486

Get the updated code, and documentation on XS code

All code updates, and documentation are pushed to our sponsorship repository, and eventually pushed into this free repository. The sponsorship repository comes with extra features, detailed/updated documentation, and priority bug fixes. Subscribe to the sponsorship repository on XS Code: https://cp.xscode.com/Kunta-Labs/AfricaOS

To start a single node

Edit the Makefile in /core/ to input the IP addresses, and ports for your other nodes. This version comes with a 3-node setup, for Alice, Bob, and Cici (the default is 127.0.0.1:x, to run all 3 nodes on a single workstation.

make alice # from inside ./core/

To reset Alice

make clean_alice # from inside ./core/

To start 3-node network

To create Bob, copy the folder, and create another folder one level up from the projects root, and run the same command for bob

make bob # from inside ./core/

To reset bob,

make clean_bob # from inside ./core/

Do the same for Cici

make cici # from inside ./core/

Now they should be pointed to each other from a peer perspective

Begin proposal generation

This will submit a first proposal to alice, which will initiate proposal generation amongst each node (alice, bob, and cici)

make p_alice # from inside ./core/

Stress with output/female transaction

To create/submit a new transaction every m seconds

make stress # from inside ./core/

This will create one output tx

make stress_output # from inside ./core/

This will create an input tx for that output

tx_hash=< OUTPUT-TX-HASH > make stress_input

Viewing state from your container

docker cp 8dcbe580eb6f:storage/states.db ./states.db ; cat ./states.db ; rm ./states.db

Docker

To build the core docker container, run (from inside ./)

make dbm # stands for "docker build main"

this will build the container from source

Pulling AOS core container

to pull a minimal docker image of AfricaOS, run

docker pull kuntalabs/africaos:latest

Running 3-node network

to run the 3 containers, and set up the 3-node network, run (from inside ./core/)

make rac #  or make dbm, stands for "run all containers"

Transactions

Combined txs will have the following default values (this is to be customized for your use case):

<partner_sender> <partner_tx_hash> <sig> <pk> <pkhash> <amount>

Output

<pkhash> <amount>

Senders submit the hash of the receivers public key to the blockchain, and the amount to send to the receiver

Input

<partner_sender> <partner_tx_hash> <sig> <pk>

Receivers submit the sender of the amount, the hash of the output transaction, their signature of an arbitrary string (default: "TEST"), and finally the receiver's public key

Generating new keys

make new_keys

Customization

We expose common customization points

  • Block Validation
  • Proposal Validation
  • Proposal Creator Election
  • Transaction Output Logic
  • Transaction Input Logic

To Contribute

TODO:

  • Submit Issue using template

under active development

Discord

https://discord.gg/dMvtDeW

Telegram

http://t.me/africaos

africaos's People

Contributors

jovonni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

africaos's Issues

Parse Header Error on peer response

Error(
    Hyper(
        Error(
            Parse(
                Header,
            ),
        ),
    ),
    "http://<IP>:<PORT><ENDPOINT>",
)

Executed by lines:

let response_result = format!( "HTTP/1.1 200 OK
\r\nContent-Length: 1000
\r\nContent-Type: application/json; charset=UTF-8
\r\n\r\n{}
\r\n", result );

Format should follow

HTTP-Version Status-Code Reason-Phrase CRLF
headers CRLF
message-body

as shown in:
https://doc.rust-lang.org/book/ch20-01-single-threaded.html#writing-a-response

Example response:
HTTP/1.1 200 OK

instead of fire-first network requests, node should request to transmit

The mechanism to request should be configurable
For example, behavior like:

if Server::broadcast_proposal_response(proposal.clone(), peer.clone().location, node_ip.clone(), ProposalStatus::Accepted).is_ok() {
    DB::update_proposal(proposal.clone(), "accepted_broadcasted");
} else {
    ...
}

should be requested first, or only allowed to be submitted to a node if the node states it is available to receive requests.

After days of constant TXs, a Proposal/Block is eventually executed twice on the proposal's creators node

This is due to:

let block_commit_result: Result<(),String> = Block::commit_if_valid(proposal.clone().proposal_block);

being invoked upon accepted_by_network state, regardless of the state of the last proposal. So when a proposal is commited on disk, it still will reference the proposal in memory, not from disk. This could cause a race condition.

Also,

ValidateProposalBlock

has a block commit with no proposal condition, so by the time a node got here, if a third node broadcasted a resolution to the first node, it will attempt to execute this again.

Block::commit_if_valid(self.clone().proposal_block)

Remove hardcoded test public key from signature verification, pass as parameter

Remove hardcoded public key, and pass into verify. Will change tests as well.

let public_key_base64: &str = "MIIBCgKCAQEAuJ3hhGpo+nInkqHpgBx3E5eihx0IGNVit5u0UlvLHmnW2PJ3HqFyafr/eYaas7VetW5Ss5kAWZmH3oED7n4xVlXrUeFlSwShSDVMKyT3iK1et1KQIX5cqp2CiFSs+xi5eJOEEWZxoexYbSTg0Rg34gzob+VqHZzRtRN9eTja7ZCE3/m3cMlWfb7yL2jyN521ZL02QG9PZ4EYenDTM2xcWvCZrWtKUFLahCWWQ1H8ZpoWg/y/tenvUy5YnWLrbhbSZqMJQYfnUwr8FRWZsiI2RWRtXlx9X6bxvaOoG/h4IOhV/G52Xas2WxxUbZ5rgRPziA/mvkJxytHkZPeEnpRcawIDAQAB";

Also alter the function in the Verifier trait to accept base64 pub key as parameter:

let content: &str = "TEST";
let signature_result: &str = "opEssZ7CaoYvtZJErFPqiB0L+lxwFm1/YT3tLZ+07fCnwWvuRcXtpwmo4esdNs05OItDBK6SZaxVPO+tKG22NC8R64DQj4J6CXpt4XMxtGJSUeY9MyZB6eyW8qYye7zascGv5+Eht4VJ5Zu9TX8Xl2+oyZA+3RYw5QKHvMgHyN0mpPU8PYpBDdVKg5Nglh4WOjqrvJF/EAdyqfeLN0CNJHeFwwjlkDaOz1x9LBOBf8c5HhDulgblSd4tlJ9zRA97SbnxmQtip/XDLweTtCx9vmjFd0tw/JTcfl2V87r+JgxL0r9EgEoFsexs3XkdqKZ2LzypPMvp0XqeoNEJ03g96A==";
let public_key_base64: &str = "MIIBCgKCAQEAuJ3hhGpo+nInkqHpgBx3E5eihx0IGNVit5u0UlvLHmnW2PJ3HqFyafr/eYaas7VetW5Ss5kAWZmH3oED7n4xVlXrUeFlSwShSDVMKyT3iK1et1KQIX5cqp2CiFSs+xi5eJOEEWZxoexYbSTg0Rg34gzob+VqHZzRtRN9eTja7ZCE3/m3cMlWfb7yL2jyN521ZL02QG9PZ4EYenDTM2xcWvCZrWtKUFLahCWWQ1H8ZpoWg/y/tenvUy5YnWLrbhbSZqMJQYfnUwr8FRWZsiI2RWRtXlx9X6bxvaOoG/h4IOhV/G52Xas2WxxUbZ5rgRPziA/mvkJxytHkZPeEnpRcawIDAQAB";
match Encoder::base64_to_bytes( String::from(public_key_base64) ) {
Ok(public_key_bytes) => {
let verification_result: Result<String, SignatureError> = Signature::verify(digital_signature, String::from(signature_result), content);

Change from

Signature::verify(digital_signature, String::from(signature_result), content); 

to

Signature::verify(digital_signature, public_key_base64, String::from(signature_result), content); 

Add support for additional extensions on output/input tx

For example, since components of each tx are referenced directly, we can add checks for additional data, and run error-handled computation before/after main tx execution process:

let tx_sections: Vec<&str> = decoded.split(" ").collect::<Vec<_>>();
let partner_tx_sender: String = String::from(tx_sections[0]);
let tx_partner_hash: String = String::from(tx_sections[1]);
let tx_signature: String = String::from(tx_sections[2]);
let tx_public_key: String = String::from(tx_sections[3]);
// id state has the sender key
if state_as_json.has_key( &(format!("{}", tx_partner_hash).to_string()) ) {
let partner_tx: Option<&str> = state_as_json[ tx_partner_hash ].as_str();
// if partner hash exists
if partner_tx.clone().is_some() {
println!("INPUT: partner tx: {}", partner_tx.unwrap());
//let b64_decoded_partner: Result<String, String> = Encoder::decode_base64($tx_data);
let b64_decoded_partner: String = Encoder::decode_base64( String::from( partner_tx.clone().unwrap() ) ).unwrap();
println!("INPUT: b64_decoded_partner: {}", b64_decoded_partner);
let partner_tx_sections: Vec<&str> = b64_decoded_partner.split(" ").collect::<Vec<_>>();
// let partner_tx_sender: String = String::from(partner_tx_sections[0]);
let public_key_hash_section: String = String::from(partner_tx_sections[0]);
let partner_amount_section: String = String::from(partner_tx_sections[1]);

Sign partner transaction hash instead of static String

// TODO: check signature
let digital_signature: DigitalSignature = signature::DigitalSignature {
signature_type: signature::SignatureType::RSA,
format_type: signature::SignatureFormat::DISK
};
// TODO: sign transaction has instead of static str
let content: &str = "TEST";
let signature_result: &str = tx_signature.as_str();
let public_key_base64: &str = tx_public_key.as_str();
//convert base64 public key to bytes
match encode::Encoder::base64_to_bytes( String::from(public_key_base64) ) {
Ok(public_key_bytes) => {
let verification_result: Result<String, signature::SignatureError> = Signature::verify(digital_signature, String::from(signature_result), content);

proposal_creator_election macro are +/- off by 1 because congruence

bug quoted from the paper repo:
paper issue

The proposal creation function still iterates congruently, but the expected node id is not what is expected. All tests pass now, but this is was the bug. It didn't stop proposal generation for nodes, but it chose the wrong participant to create the next proposal

wrong:

( ($latest_block_id + 1) % ( ($peer_length + 1) as i64) ) + 1

Should be:

($latest_block_id % $peer_length as i64) + 1

Because

[print( ( (x+1) % (3 + 1) ) + 1 ) for x in range(0,10)]
2
3
4
1
2
3
4
1
2
3

but this is correct

[print((x % 3) + 1) for x in range(0,10)]
1
2
3
1
2
3
1
2
3
1

This works for three, and for 2 peers

[print((x % 2) + 1) for x in range(0,10)]
1
2
1
2
1
2
1
2
1
2

and for 5 peers

[print((x % 5) + 1) for x in range(0,10)]
1
2
3
4
5
1
2
3
4
5

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.