generic-sidechain-high-level-design
Objective
This document is intended to outline generic design of sidechain plugin used by Peerplays Node, to monitor and process events of interest on a target sidechain nodes. This interface will be extended to meet various other integrations.
Assumptions
Sidechain plugin purpose is to monitor and process events of interest on a multiple target sidechains.
Sidechain node provides interface for monitoring changes in a sidechain.
Monitoring is based on new block, new transaction or filtered single event (like transfer operation to specific address).
There is a sufficient C/C++ library for connecting to monitoring interface.
Sidechain node provides communication interface which sidechain handler can use to read all the required info about event of interest. E.g. HTTP/RPC…
Block Diagram
Link to Draw.io file
https://drive.google.com/file/d/1BXeRwK_2PNt6wMnzIl8M6OMRnuM5CumQ/view?usp=sharing
Description
Peerplays Sidechain is implemented as a plugin.
Sidechain Manager is a component in a Peerplays Plugin, which contains a collection of Sidechain Handlers.
No multiple sidechain handlers for same network is allowed.
No communication between sidechain handlers is allowed or needed.
One Sidechain Handler handles only one sidechain network.
Each Sidechain Handler monitors and processes events of interests on its target network.
Each Sidechain Handler implements only sidechain specific processing, eg reading transaction info, parsing transaction data, etc…
The result of Sidechain Handler processing saved into peerplays network for further processing
In general, Sidechain Handler contains event listener, communication interface and event handler.
Event listener is “listening” for events on a sidechain. When event happens, event listener will notify event handler about incoming event.
Event handler uses communication interface to read all the information needed in order to process the event.
Once the processing is finished, event handler will pass the result to the Sidechain Manager, for further processing.
Sequence diagram
Link to draw.io file
https://drive.google.com/file/d/17kbez7C1Djaj-2AgyEzQ1Z-5CrSZ5wZE/view?usp=sharing
For the simplicity, sequence diagram shows interactions between components in a single sidechain handler.
Suggested implementation
peerplays_sidechain_plugin is a class implementing a peerplays sidechain plugin.
Contains the instance of sidechain_manager
sidechain_manager is a class implementing Sidechain Manager
Contains the collection (std::vector) of sidechain_handlers
Contains the factory method for creating instance of sidechain_handler for particular sidechain
Factory method parameters include program options, used to pass configure options to a sidechain handler
Contains methods for calling sidechain_handlers methods for processing events of interest
recreate_primary_wallet This method will initiate recreation of primary wallet on active SON set change, if needed
process_deposits This method will call sidechain handlers method for processing sidechain deposits
process_withdrawals This method will call sidechain handlers method for processing sidechain withdrawals
sidechain_handler is a base class for implementing sidechain handlers
Needs to have access to user sidechain address mapping list, in order to filter events by checking addresses involved in a transaction against the list of addresses of interests.
sidechain_type get_sidechain() Gets the sidechain type
std::vectorstd::string get_sidechain_deposit_addresses() Gets the list of deposit addresses for a sidechain
std::vectorstd::string get_sidechain_withdraw_addresses() Gets the list of withdrawal addresses for a sidechain
std::string get_private_key(std::string public_key) Gets the private key for a given public key, for signing sidechain transactions
Needs to contain method receiving the data structure describing event of interest as the parameter
sidechain_event_data_received(const sidechain_event_data &sed)
// Sidechain type
enum class sidechain_type {
bitcoin,
ethereum,
eos,
peerplays
};
struct sidechain_event_data {
fc::time_point_sec timestamp; // time when event was detected
sidechain_type sidechain; // sidechain where event happened
std::string sidechain_uid; // transaction unique id for a sidechain
std::string sidechain_transaction_id; // transaction id on a sidechain
std::string sidechain_from; // sidechain senders account, if available
std::string sidechain_to; // sidechain receiver account, if available
std::string sidechain_currency; // sidechain transfer currency
fc::safe<int64_t> sidechain_amount; // sidechain asset amount
chain::account_id_type peerplays_from; // perplays senders account matching sidechain senders account
chain::account_id_type peerplays_to; // peerplays receiver account matching sidechain receiver account
chain::asset peerplays_asset; // transfer value in peerplays core asset
};
For deposits, sidechain handler will create deposit descriptor object son_wallet_deposit_object, using data from sidechain_evend_data structure
class son_wallet_deposit_object : public abstract_object<son_wallet_deposit_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_wallet_deposit_object_type;
time_point_sec timestamp;
peerplays_sidechain::sidechain_type sidechain;
int64_t confirmations;
std::string sidechain_uid;
std::string sidechain_transaction_id;
std::string sidechain_from;
std::string sidechain_to;
std::string sidechain_currency;
safe<int64_t> sidechain_amount;
chain::account_id_type peerplays_from;
chain::account_id_type peerplays_to;
chain::asset peerplays_asset;
bool processed;
};
For withdrawals, sidechain handler will create withdrawal descriptor object son_wallet_withdraw_object, using data from sidechain_event_data structure
class son_wallet_withdraw_object : public abstract_object<son_wallet_withdraw_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = son_wallet_withdraw_object_type;
time_point_sec timestamp;
peerplays_sidechain::sidechain_type sidechain;
int64_t confirmations;
std::string peerplays_uid;
std::string peerplays_transaction_id;
chain::account_id_type peerplays_from;
chain::asset peerplays_asset;
peerplays_sidechain::sidechain_type withdraw_sidechain;
std::string withdraw_address;
std::string withdraw_currency;
safe<int64_t> withdraw_amount;
bool processed;
};
Contains following abstract methods (the list can change anytime):
virtual void recreate_primary_wallet() = 0; Method is called by sidechain manager, to recreate the primary wallet on a sidechain, if needed
virtual void process_deposit(const son_wallet_deposit_object &swdo) = 0; Callback method, called for each deposit that needs to be processed by a sidechain handler
virtual void process_withdrawal(const son_wallet_withdraw_object &swwo) = 0;
Callback method, called for each withdrawal that needs to be processed by a sidechain handler
sidechain_handler_bitcoin is a class, inheriting sidechain_handler, implementing sidechain handler for Bitcoin
Listener may be implemented by ZeroMQ (also spelled ØMQ, 0MQ or ZMQ), high-performance asynchronous messaging library
Communication interface may be implemented as HTTP client, using RPC bitcoin node interface
Implement any RPC call that might be needed
std::string addmultisigaddress(const std::vector<std::string> public_keys);
std::string createrawtransaction(const std::vector<btc_txout> &ins, const fc::flat_map<std::string, double> outs);
std::string createwallet(const std::string &wallet_name);
std::string encryptwallet(const std::string &passphrase);
uint64_t estimatesmartfee();
std::string getblock(const std::string &block_hash, int32_t verbosity = 2);
void importaddress(const std::string &address_or_script);
std::vector<btc_txout> listunspent();
std::vector<btc_txout> listunspent_by_address_and_amount(const std::string &address, double transfer_amount);
std::string loadwallet(const std::string &filename);
void sendrawtransaction(const std::string &tx_hex);
std::string signrawtransactionwithkey(const std::string &tx_hash, const std::string &private_key);
std::string signrawtransactionwithwallet(const std::string &tx_hash);
std::string unloadwallet(const std::string &filename);
std::string walletlock();
Implements abstract methods:
void recreate_primary_wallet() override; Method is called by sidechain manager, to recreate the primary wallet on a sidechain, if needed
void process_deposit(const son_wallet_deposit_object &swdo) override; Callback method, called for each deposit that needs to be processed by a sidechain handler
void process_withdrawal(const son_wallet_withdraw_object &swwo) override; Callback method, called for each withdrawal that needs to be processed by a sidechain handler
sidechain_handler_ethereum is a class, inheriting sidechain_handler, implementing sidechain handler for Ethereum
TBD
sidechain_handler_eos is a class, inheriting sidechain_handler, implementing sidechain handler for EOS
TBD
sidechain_handler_peerplays is a class, inheriting sidechain_handler, implementing sidechain handler for Peerplays
Listener can be implemented as a callback of database.applied_block signal. This will give us access to newly created blocks, and its content.
Communication interface, like RPC client from Bitcoin handler, is not really needed, as we can read all the data we need from blockchain database.
Implements abstract methods:
void recreate_primary_wallet() override; Method is called by sidechain manager, to recreate the primary wallet on a sidechain, if needed
void process_deposit(const son_wallet_deposit_object &swdo) override; Callback method, called for each deposit that needs to be processed by a sidechain handler
void process_withdrawal(const son_wallet_withdraw_object &swwo) override; Callback method, called for each withdrawal that needs to be processed by a sidechain handler
sidechain_handler_* is a class, inheriting sidechain_handler, implementing sidechain handler for *
Any future sidechain
TBD
Last updated