Click here to Skip to main content
15,867,308 members
Articles / Security / Blockchain

How to Implement a Custom Blockchain for Your Business: Graphene Framework

,
Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
5 Feb 2019CPOL15 min read 6.6K   6  
The experience of creating a custom blockchain network using the Graphene framework.

Introduction

Though a blockchain is just a distributed ledger with an immutable chain of data, blockchains can be successfully implemented in various business spheres. They’re helpful if you need to keep track of records or make them unchangeable. And peer-to-peer networks allow you to restore information in case of data loss.

On the other hand, using one of the most popular public blockchain networks for your company isn’t really safe, because your sensitive data will be accessible to everyone. Also, a public blockchain can simply lack some functionality needed for your business needs.

The Graphene framework speeds up the design of custom blockchain networks while enabling to implement your business logic. In this article, one of our Apriorit blockchain experts shares his experience creating a custom blockchain network using the Graphene framework.

Contents

Pros and Cons of a Private Blockchain Network

A blockchain network can meet the requirements of various kinds of businesses. Here are some examples of how blockchain networks can be applied to different business purposes:

  • Logistics – Keep track of shipments and deliveries
  • Client records – Check and record a client’s history
  • Work management – Place work orders and track progress
  • Finance – Provide infrastructure for cross-border transactions, accounting, and auditing

With so many public blockchain platforms out there, you’ll probably be able to find one that more or less meets your needs. However, there are two things to consider before creating a public blockchain:

  • Any data on a public network is accessible to all network members, among which may be unrelated or malicious users. Therefore, you can’t store any sensitive information on a public blockchain.
  • You’ll become dependent on the host network. If anything happens to the main network, your application will be vulnerable.

So if privacy and independence are important for your company, a custom blockchain implementation is the obvious choice.

On the other hand, creating and implementing your own blockchain network is a big challenge. Let’s consider two possible ways of creating a blockchain for your business.

Developing Your Own Blockchain vs Customizing an Existing Solution

There are three ways to implement blockchain technology in your business. Let’s look at them:

  1. Create a custom blockchain network. The main advantage of this approach is that a custom network can meet any and all requirements. You’ll have control over each stage of development, with the ability to implement any changes and business rules you need. On the other hand, creating such a network is not an easy task. You’ll have to develop a consensus algorithm, implement a peer-to-peer network, design communication protocols, and more. This requires a lot of time and effort from your development team and therefore can be quite expensive. On top of that, you’ll have to ensure that your network has no bugs and is safe to use.
  2. Create a private network based on an existing blockchain. Almost every mainstream blockchain supports private networks. You can create a copy of the public network in your private environment. This private network will contain only your data and handle your transactions. It will be incompatible with the main network, so external peers won’t be able to synchronize with the private chain. Deploying your favorite blockchain on a local server and setting up a running network will take just a few hours. The downside of a private network is the lack of customization. Changing some core network properties, such as the consensus mechanism, will require modifying the network’s source code. Depending on the software architecture, this may be difficult.
  1. Build a private blockchain on the Graphene framework. This method combines the best features of the two previous approaches. It allows you to make a fully custom blockchain network without researching and developing complex consensus mechanisms and an advanced peer-to-peer networking solution. The Graphene framework provides you with all necessary functionality and makes it easy to create a custom blockchain that suits your own business logic.

The Graphene Framework

The Graphene framework is a solution for creating custom blockchain implementations. It contains all the components required for creating a working network. At the same time, Graphene blockchain development leaves room for implementing the business logic your company needs. So this framework is perfect for automating business processes with a blockchain.

Graphene comes pre-packaged with the following components:

  • A barebones blockchain implementation with data storage
  • An efficient and advanced consensus algorithm
  • A complete P2P networking solution with HTTP APIs
  • A framework for adding custom functionality
  • Elliptic-curve cryptography, hashing, block construction, etc.

Implementing a blockchain using Graphene technology allows you to focus on your business needs without worrying about details of network development. Moreover, the framework is modular. You can easily change any parts. You can do anything from adding custom commands to the command-line interface (CLI) to changing the entire consensus algorithm.

Compared to existing popular blockchain implementations, the basic Graphene framework allows you to build interactions faster, thanks to its advanced consensus mechanism.

The blockchain framework uses an algorithm called delegated proof of stake, or DPoS. This algorithm selects trusted delegates (or witnesses), which can produce blocks with no additional mining required. Witnesses are selected by an approval vote. Anyone holding the native network currency can vote for their favorite witness. During each maintenance period in Graphene, these votes are recounted and the top witnesses are selected to create new blocks and maintain the ledger. The witnesses receive a reward for maintaining the ledger. The total number of witnesses and conditions for becoming one can be configured manually. This allows Graphene to work more efficiently than classic proof-of-work (PoW) blockchain networks.

Usually, a witness:

  • is a known entity (no anonymous witnesses)
  • is trusted by stakeholders
  • has the capacity to run and maintain a full node

The DPoS consensus is organized so that all witnesses are equal, even if one of them has many more votes. So there’s no chance for a 51% attack, as in PoW networks.

Smart contracts in Graphene blockchain technology are tied to the network itself. This improves scalability and performance. And while it’s less flexible than other solutions (such as EOS and Ethereum), the business logic of an existing network still can be updated or changed with Graphene.

Graphene is the basis for several known blockchain networks:

  • BitShares
  • Steem
  • Peerplays
  • BitEthereum
  • Smoke
  • Scorum

Each of these networks introduces some specialized functionality on top of the Graphene core. For example, EOS adds support for advanced smart contracts. Steem adds media tokens and other smart assets.

The most famous of these networks is BitShares. It inherits all the benefits of Graphene, such as speed and scalability, and adds many features including price-stable cryptocurrencies (smart coins), decentralized asset exchange, and automatic recurring payments.

These examples show just how customizable Graphene is.

The Smart Contract Module in Graphene

Graphene doesn’t have smart contracts in the usual sense. Instead, all of your business logic is embedded in the network. In other words, in order to create a smart contract, we need to modify the Graphene source code.

A Graphene blockchain implementation allows us to easily add custom actions to the network. An action or an operation in Graphene is just a function within the source code with several additional requirements:

  • The operation arguments must be a struct so that transaction parameters can be stored on the blockchain.
  • The operation must have a validate() function that performs a sanity check of the parameters. This function checks if the arguments are well-formed, meaningful, and placed within a predefined range. For example, you may check that a user doesn’t transfer tokens to themselves since it’s a pointless operation.
  • The operation must have an evaluator. The evaluator is the actual brain behind the operation. It contains two functions:
    • do_evaluate(), which checks parameters like function validation. This function performs higher-level validations such as Does the user have enough tokens to transfer? and Has the contract expired? These are more than simple input confirmations; they’re an actual part of the business logic.
    • do_apply(), which applies the necessary changes. For example, it can update the user’s balance, change data stored on the blockchain, etc.

Overall, an operation executes like this:

The Graphene framework has a specific mechanism for creating a smart contract.

Groups of such operations form smart contracts on the Graphene platform. Obviously, since these “smart contracts” are embedded into the source code, there’s no easy way to change them once the network is running. However, this approach has two benefits as compared to simply deploying a smart contract on a private network:

  1. Speed – The smart contract is compiled into native executable instructions just as the rest of the network’s code. This way, the smart contract executes as fast as possible, with no additional overhead of a virtual machine (unlike with EVM in Ethereum or WASM in EOS).
  2. Security – Removing the ability to add custom smart contracts, Graphene gets rid of one of the major attack vectors.

Further Modification of the Graphene Network

Once the blockchain network is up, you can continue to adjust it according to your business demands. This is especially useful in case you need to implement a primary feature block as fast as possible and work out the rest in your free time.

There are several ways to expand your network functionality:

  • Add more options to access smart contract operations. Adding commands to the CLI will help a lot during testing, and a great GUI will surely attract many users.
  • Add more advanced operations to smart contracts. For example, you can add automatic functionality during network maintenance to clean up expired data or update account states.
  • Support operations between contracts, for example, issuing and accepting payments using custom tokens. And of course, you can refine protocols and improve existing functions.
  • Change the core functionality of the framework. For example, if all of your block producers can be trusted, you don’t need the advanced consensus mechanism present in Graphene.

Performing a Network Update

Data on any blockchain network is permanent. If you want to perform an update – or even add some functionality to your network – you’ll have to perform a hard fork. Blocks added to a chain after the hard fork will be incompatible with the old consensus due to the changes.

A hard fork makes new blocks incompatible with the old ones.

As you can see, at a specified point, all nodes switch to the modified verification algorithms. There’s no actual split. However, since the new blocks are incompatible with the old ones, this is called a hard fork.

A convenient way to implement a similar update in Graphene is to place a hard fork guard around each changed part of the code like this:

C++
FC_ASSERT( db().head_block_time() > HARDFORK_NEW_FEATURE_TIME,  
// New code is added after this point
          "Operation not allowed before HARDFORK_ NEW_FEATURE _TIME.");

Where HARDFORK_ NEW_FEATURE _TIME is a constant that contains the time when the hard fork should occur.

Example Using the Graphene Framework

To show you an example of this technology, we’ll develop a blockchain on the Graphene framework. Let’s create a network for musicians and producers. In order to keep our example simple, we’ll implement only basic business logic, so it might not cover some specific cases.

There are three actors in our example:

  • A user buys music with cryptocurrency embedded in our network.
  • A producer (or a studio) sells albums to users and makes the profit.
  • A musician negotiates a contract with a producer in order to release an album.

In this network, a producer creates a contract that includes an estimate and a reward. A musician accepts it and creates an album. If the contract is fulfilled, the musician gets their reward. If not, the producer gets their money back. To keep our network simple, any other activity connected with contracts and music happens off-chain.

Our sample network will provide the following functionality:

  • The ability for musicians and producers to safely create contracts:
    • Create a contract
    • Agree on the terms of the contract
    • Complete the contract and distribute rewards
    • Handle incomplete and expired contracts
  • The ability to sell musical albums and distribute profits according to a contract.

Our blockchain will act as the backend for these operations. The general procedure for creating a music contract looks like this:

The general procedure for creating a music contract includes creating, signing a contract, and publishing an album.

Or, if the contract expires, the procedure looks like this:

If a contract expires, a producer gets a refund.

Selling an album is just as simple as exchanging native cryptocurrency for the album. By default, all profit goes directly to the producer, but this can be configured in the contract and a percentage may be shared with the musician.

All of this functionality is achievable with a smart contract. However, for our purposes, a separate network is required. For example, we may want to attract users by providing free transactions, which is usually impossible with a smart contract on an existing network.

Adding a Data Structure

Before we start creating operations for our network, we must define what types of data will be available. This data will be stored in the state database on the blockchain.

So the full structure will look like this:

C++
class music_contract_object: public graphene::db::abstract_object < music_contract_object > {  
  public: static  
  const uint8_t space_id = implementation_ids;  
  static  
  const uint8_t type_id = impl_ music_contract_object_type;  
   
  uint32_t contract_id = 10;  
  account_id_type producer;             // the account id of the producer  
  account_id_type musician;             // the account id of the musician  
  asset amount;                         // contract amount  
  time_point_sec ratification_deadline; // deadline till the contract must be signed  
  time_point_sec contract_expiration;   // contract expiration time  
  asset pending_fee;                    // fee for creating the contract  
  bool musician_signed = false;         // whether the musician signed the contract  
};

To use the defined data structure, we must create a database object index. This index is used just for the storage backend. And then, we can register the object with the database like this:

C++
void database::initialize_indexes()
{
 . . .
    add_index< primary_index<music_contract_index>>();
}

Defining the Operations

We’ve already specified operations and validators of our network in previous sections of this article. Let’s introduce the key actors and functionality for creating smart contracts on our network. At this point, we can define it this way:

C++
struct music_contract_create_operation : public base_operation {
    struct fee_parameters_type {
        uint64_t fee       = 1 * GRAPHENE_BLOCKCHAIN_PRECISION;
    };
    asset              fee;
    account_id_type    producer;
    account_id_type    musician;
    asset              amount;
    uint32_t           contract_id=0;
    string             details;
    time_point_sec     ratification_deadline;
    time_point_sec     contract_expiration;
    void validate()const {
        FC_ASSERT( amount.amount > 0 );
        FC_ASSERT( producer != musician );
    }
    void get_required_active_authorities( flat_set<account_id_type>& a )const{ a.insert(producer); }
    account_id_type fee_payer()const { return producer; }
};

We can create other operations with contracts in a similar way. The next step is adding evaluators that check the parameters of a smart contract, such as estimated deadlines and the ability of some network users to act as both musicians and producers:

C++
class contract_create_evaluator : public evaluator< contract_create_evaluator>
{
    public:
    typedef music_contract_create_operation operation_type;
    void_result do_evaluate( const music_contract_create_operation& o );
    object_id_type do_apply( const music_contract_create_operation& o );
};
void_result contract_create_evaluator::do_evaluate(const music_contract_create_operation& o)
{
    FC_ASSERT( o.ratification_deadline > db().head_block_time() );
    FC_ASSERT( o.contract_expiration > db().head_block_time() );
    if(o.amount.asset_id == asset_id_type())
        FC_ASSERT( db().get_balance( o.producer, o.amount.asset_id ) >= (o.amount + o.fee) );
    return void_result();
}
object_id_type contract_create_evaluator::do_apply(const music_contract_create_operation& o)
{
    try {
       db().adjust_balance( o.producer, -o.amount );
       const music_contract_object& ctr = db().create<music_contract_object>([&]
                                                 ( music_contract_object& ctr) {
            ctr.contract_id                = o.contract_id;
            ctr.producer                   = o.producer;
            ctr.musician                   = o.musician;
            ctr.amount                     = o.amount;
            ctr. pending_fee               = o.fee;
            ctr.ratification_deadline      = o.ratification_deadline;
            ctr.contract_expiration        = o.contract_expiration;
       });
       return  ctr.id;
    } FC_CAPTURE_AND_RETHROW( (o) )
}

Now we have a functional smart contract that can check parameters and perform actions accordingly. Unfortunately, there’s no way to use it from outside the source code. There are two ways you can access the smart contract: using the command-line interface or via the HTTP API. Of course, for a real project, you may want to implement both, or even implement a GUI using your smart contract operations directly. For now, a basic HTTP API will be enough to test our operations.

Accessing the Operations

Creating a simple API for your smart contract is straightforward. First, we have to define a class that will contain all of the functions accessible via HTTP:

C++
class music_api
   {
      public:
         music_api(graphene::chain::database& db);
         ~music_api();
      /* explain */
         optional<music_contract_object>  
                    get_contract( account_id_type publisher, uint32_t contract_id ) const;
      private:
         graphene::chain::database& _db;
      }; 
. . .
   optional<music_contract_object>  get_contract
                   ( account_id_type publisher, uint32_t contract_id ) const
   {
      optional< music_contract_object > result;
      try
      {
         result = _db.get_contract( publisher, contract_id );
      }
      catch ( ... ) {}
      return result;
   }

Then, we have to register the API and its functions using the FC_API macro:

C++
FC_API(graphene::app::music_api,
       (get_contract)
       . . .
     )

Building the Node

Now we can move on to building the node executable. The process goes like this:

  1. Install some necessary libraries and GCC 4.9.
  2. Download and build Boost 1.57.0 (make sure to use the same compiler version for building Boost, your prototype, and other Graphene parts).
  3. Compile the executables using make.

Here are some useful tips that can help you avoid mistakes during the build process:

  • Use enough RAM. Building a project requires at least 4 GB of RAM. This may be an issue if you’re building on a virtual machine. Don’t forget to allocate enough RAM to the VM beforehand to avoid starting over.
  • Create a Docker container for your builds. This allows you to configure the built environment once and use it anywhere.
  • Make sure to use the specified versions of the Boost library and GCC. The build process requires precise library versions. It’s possible to build using newer versions, but this may take a lot of effort.

The GUI wallet is optional and requires building a separate version of the QT Framework, which may take a long time. You can save a lot of time by skipping it during the build process unless you specifically want to develop the GUI wallet.

Deploying and Setting Up the Network

Once you have all the necessary executables, deploying the network is simple. You can start a Graphene witness node by running:

./programs/witness_node/witness_node 

You can open RPC to access the node from wallets using the flag:

--rpc-endpoint 127.0.0.1:8090

And to enable block production, you can use the flag:

--enable-stale-production

You can access the witness node directly through HTTP requests using curl, or access it through the included CLI or GUI wallet. However, in order to have your contract operations available as commands in the wallet, you must modify the wallet source code by adding the appropriate calls.

Consensus Algorithm

Graphene has a unique consensus algorithm that can receive a special application in our example. In our case, producers and studios fit the description of witnesses. Moreover, we can modify the voting process to include album sales rather than direct votes in order to select top witnesses for block generation.

Note that in terms of a smart contract, there’s no difference between a producer with a witness node and one without. However, since we control the network, it’s possible to limit the list of producers only to registered customers. Any additional requirements can be made in order for a producer to join the network, including running a witness node.

Conclusion

A blockchain network offers great promise for your business. But existing blockchain networks can be slow and expensive. And with a public network, you’re putting the fate of your business in the hands of outsiders. Creating a custom blockchain allows you to tune this technology according to your business needs.

Building a custom blockchain is difficult and expensive. However, the Graphene framework makes creating a custom blockchain network easier and cheaper.

Resourсes

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Apriorit
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --