rooot-voting-machine

command module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2020 License: AGPL-3.0 Imports: 3 Imported by: 0

README

rooot-voting-machine

Voting module for the Rooot™ blockchain

GitHub tag (latest by date) GitHub go.mod Go version GitHub last commit GitHub issues

This module is the "voting machine" used by the Rooot™ system for its consensus algorithm. It's especially suited for applications involving the node.

Motivation

In order to enforce the stability of the blockchain, Rooot™ adopts a 7-step consensus algorithm (called 3DR©), the last of which being the choice of a Block per Period. This module was built specifically to handle the voting process of this latter step. The principles of the vote are described below. The use of this module is not mandatory. Any system that leads to the same outcome would obviously be accepted. Each registered Miner should nevertheless agree to have his code audited for compliance by any other Miner if wished.

Description

The 7th (and last) step of the 3DR© consensus algorithm relies on a 3-phase procedure:

  1. The local choice of the Block for the related Period by each node using the algorithm's rules (compliance, maximum number of transactions, etc.);
  2. A "voting" process during which each node asks his neighbours what is their choice for this Period;
  3. The actual decision and writing of the chosen Block.

When the voting process took place, the rule for the node to decide which Block to choose is the following:

  • if the node didn't build a Block (ie. he's a "light" node), he should choose the valid Block that has gained the most vote for;
  • if a majority emerges for a Block from the neighbours and it's also the node's choice, the voted Block is chosen;
  • if there's a tie, the node's choice wins if he's in the tied players, otherwise he should use the regular rules to decide;
  • if the node's choice differs from the vote of the majority of its neighbours, the node should choose the neighbours' vote if, and only if, the voted Block is valid (and he must therefore recycle any Transaction (announced or mined) that wasn't taken into account in the voted Block from his own Block);
  • otherwise, if the node finds at least one other node that makes the same choice as his and it's considered a valid Block, he should keep it (they are either the only honest nodes, or they're just late and a future syncing procedure will show that to them and make them correct their blockchain);
  • as a last resort, the node should keep his own Block (mostly in case there's a communications problem that prevents him from having his neighbours' votes or send his own, or if he considers no voted Block is valid).

In any case, the node must frequently re-sync his blockchain with his peers and eventually rebuild it accordingly.

Usage
$ go get github.com/edgewhere/rooot-voting-machine

The following example shows how to use it within the framework of a Rooot™ node:

import (
    "rooot/node/ws"

    "github.com/edgewhere/rooot-node-lib/models/ws/peer"
    "github.com/edgewhere/rooot-voting-machine/core/voting"
    "github.com/edgewhere/rooot-voting-machine/core/ws/handlers"
    "github.com/edgewhere/rooot-voting-machine/models/election"
    "github.com/edgewhere/rooot-voting-machine/models/p2p/message"
)

// Init the system using the node's websocket server
ws.AddHandler(message.VOTE_REQUEST, handlers.WsVoteRequest)
ws.AddHandler(message.VOTE_RESPONSE, handlers.WsVoteResponse)

go func(nodeID string, previousBlockID model.Hash, proposedAndCheckedBlocks block.Blocks, ownBlock *block.Block, peers map[string]*peer.Peer) {
    // Start an election
    newElection := election.Election{
        PeriodID: 12345678,
        Blocks: proposedAndCheckedBlocks,
        OwnBlock: ownBlock, // `nil` if it's a "light" node
        PreviousBlockID: previousBlockID,
        Voters: peers,
        ClosingTime: 1607870503520,
    }
    if electedBlock, isDifferentFromOwn, fullVotingMachine, err := voting.Process(newElection, nodeID); err == nil {
        // Do something with the results
        if fullVotingMachine.Results.Expressed() == 1 {
            log.Warn("Only one voter!")
        } else if !isDifferentFromOwn || miners.NodePools.Check(electedBlock.BlockID) || checking.IsValidBlock(electedBlock) {
            // Write it to blockchain
        } else {
            // Handle it
        }
    }
}(conf.NodeID.String(), previousBlockID, proposedAndCheckedBlocks, &myBlock, ws.PeersList())

NB: In the above example, the passed myBlock should refer to the result of the blocks.ChooseBlock() function in the node. NB 2: The previousblockID refers to the one that should be in the node's own Block. If it's a "light" node, it should refer to the penultimate mined Block.

As shown, the main process for each election should be embedded in a dedicated goroutine because it's a blocking procedure at least for the duration of the vote, ie. until the passed closing time.

License

The use of any Rooot™ library is subject to fees for commercial purpose. Please contact us to get further information. In any case, the use of this module is subject to the respect of the GNU AGPL-3.0 license.


© 2020-2021 Edgewhere SAS. All rights reserved.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
common
core
ws
models
p2p

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL