Overview

In the Cellframe Node Python extensions it is possible to work with notifications when changes occur in the mempool, atom, global database synchronization, and ledger transactions. These extensions allow access to basic information about actual changes made, as well as access to the added objects and their parameters.

Basic Functionality

This example demonstrates how to:

  1. Create handler functions for notifications related to the global database synchronization, mempool, atom, and ledger.
  2. Register these handler functions to receive notifications from the network, chains, and ledger.
  3. Log the details of the changes detected in each handler function.

To utilize this example:

  1. Start or restart the Cellframe node.
  2. Check the logs for the notifications. Make sure that the networks are online for notifications to work.
from CellFrame.Network import Net
from CellFrame.Chain import Mempool
from DAP.Core import logIt
from CellFrame.Consensus import DAG, Block
 
# Create handler functions for various events in different structures:
 
def gdbsync_notificator(op_code, group, key, value, *other):
    """
    Handler for global database synchronization notifications.
 
    Args:
        op_code (str): Operation code indicating the type of change.
        group (str): The group where the changes occurred.
        key (str): The key associated with the change.
        value (bytes): The value associated with the change.
        *other: Additional arguments.
    """
    logIt.notice("GDB callback with parameters:")
    logIt.notice(f"Operation code: {op_code}")
    logIt.notice(f"Group alias: {group}")
    logIt.notice(f"Key: {key}")
    # Since the value is encoded in bytes and could be very long, we will not output it.
 
def mempool_notificator(op_code, group, key, value, *other):
    """
    Handler for mempool notifications.
 
    Args:
        op_code (str): Operation code indicating the type of change.
        group (str): The group where the changes occurred.
        key (str): The key associated with the change.
        value (bytes): The value associated with the change.
        *other: Additional arguments.
    """
    # Since all values in mempool are datums,
    # it is possible to decode them using the datumExtract() static method:
    datum = Mempool.datumExtract(value)
 
    logIt.notice("Mempool callback with parameters:")
    logIt.notice(f"Operation code: {op_code}")
    logIt.notice(f"Group alias: {group}")
    logIt.notice(f"Key: {key}")
    logIt.notice(f"Datum hash: {datum.hash}")
 
def atom_notificator(atom, size, *other):
    """
    Handler for atom notifications.
 
    Args:
        atom (bytes): The atom data.
        size (int): The size of the atom.
        *other: Additional arguments.
    """
    logIt.notice("Atom callback with parameters:")
    # An atom is either a Block at the blockchain level or an Event if used in a DAG
    try:
        block = Block.fromAtom(atom)
        event = DAG.fromAtom(atom)
 
        if block:
            hash_value = str(block.hash)
        elif event:
            hash_value = str(event.hash)
        else:
            raise ValueError("Not found block or event from atom")
 
        logIt.notice(f"Atom hash: {hash_value}")
        logIt.notice(f"Atom size: {size}")
        logIt.notice(f"Other arguments: {other}")
 
    except ValueError as e:
        logIt.error(str(e))
 
def ledger_notificator(ledger, tx, *other):
    """
    Handler for ledger transaction notifications.
 
    Args:
        ledger (Ledger): The ledger object.
        tx (DatumTx): The transaction datum.
        *other: Additional arguments.
    """
    logIt.notice("Ledger callback with parameters:")
    # tx (transaction) is a DatumTx instance.
    # For example, output its hash and date of creation:
    logIt.notice(f"Transaction hash: {tx.hash}")
    logIt.notice(f"Transaction created at: {tx.dateCreated}")
 
def init():
    # Get network object by name
    kelvpn_net = Net.byName("KelVPN")
 
    # Get ledger object for the network
    kelvpn_ledger = kelvpn_net.getLedger()
 
    # Get the main chain and the zero chain
    main_chain = kelvpn_net.getChainByName("main")
    zero_chain = kelvpn_net.getChainByName("zerochain")
 
    # Add notifications for global database synchronization (GDB)
    # Pass the additional arguments to the notifiers with the second argument.
    kelvpn_net.addNotify(gdbsync_notificator, ())
 
    # Add mempool notifications to the main and zero chains
    main_chain.addMempoolNotify(mempool_notificator, ())
    zero_chain.addMempoolNotify(mempool_notificator, ())
 
    # Add atom notifications to the main and zero chains
    main_chain.addAtomNotify(atom_notificator, ())
    zero_chain.addAtomNotify(atom_notificator, ())
 
    # Add transaction notifications to the ledger
    kelvpn_ledger.txAddNotify(ledger_notificator, ())
 
    return 0