snow

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2024 License: BSD-3-Clause Imports: 16 Imported by: 8

README

Flow of a Single Blockchain

graph LR
    A[P2P] --> B[Chain Router]
    B --> C[Handler]
    C --> D[Consensus Engine]
    D --> E[Consensus]
    D --> F[VM]
    D --> G[DB]
    D --> I[Sender]
    F --> G
    I --> A
    I --> B 

Intro

The Odyssey primary network consists of 3 built-in blockchains: the A-Chain, D-Chain, and O-Chain. All three chains rely on the Snowman consensus protocol. The A-Chain, which previously used DAG-based Odyssey consensus, was upgraded to Snowman in the Cortina network update.

The A-Chain is used to manage assets. The D-Chain is used to create and interact with smart contracts. The O-Chain is used to coordinate validators and stake. At the time of writing, the Odyssey network has ~1200 validators. A set of validators makes up a subnet. Subnets can validate 1 or more chains. It is a common misconception that 1 subnet = 1 chain and this is shown by the primary subnet of Odyssey which is made up of the A-Chain, D-Chain, and O-Chain.

A node in the Odyssey network can either be a validator or a non-validator. A validator stakes DIONE tokens and participates in consensus to earn rewards. A non-validator does not participate in consensus or have any DIONE staked but is used as a public API. Both validators and non-validator need to have their own copy of the chain and to know the current state of the mempool. At the time of writing, there are ~1200 validators and ~1800 non-validator.

Each blockchain on Odyssey has several components: the virtual machine, database, consensus engine, sender, and handler. These components help the chain run smoothly. Blockchains also interact with the P2P layer and the chain router to send and receive messages.

P2P

Outbound Messages

The OutboundMsgBuilder interface specifies methods that build messages of type OutboundMessage. Nodes communicate to other nodes by sending OutboundMessage messages.

All messaging functions in OutboundMsgBuilder can be categorized as follows:

  • Handshake
    • Nodes need to be on a certain version before they can be accepted into the network.
  • State Sync
    • A new node can ask other nodes for the current state of the network. It only syncs the required state for a specific block.
  • Bootstrapping
    • Nodes can ask other nodes for blocks to build their own copy of the chain. A node can fetch all blocks from the locally last accepted block to the current last accepted block in the network.
  • Consensus
    • Once a node is up to tip they can participate in consensus! During consensus, a node conducts a poll to several different small random samples of the validator set. They can communicate decisons on whether or not they have accepted/rejected a block.
  • App
    • VMs communicate application-specific messages to other nodes through app messages. A common example is mempool gossiping.

Currently, Odysseygo implements its own message serialization to communicate. In the future, Odysseygo will use protocol buffers to communicate.

Network

The networking interface is shared across all chains. It implements functions from the ExternalSender interface. The two functions it implements are Send and Gossip. Send sends a message of type OutboundMessage to a specific set of nodes (specified by an array of NodeIDs). Gossip sends a message of type OutboundMessage to a random group of nodes in a subnet (can be a validator or a non-validator). Gossipping is used to push transactions across the network. The networking protocol uses TLS to pass messages between peers.

Along with sending and gossiping, the networking library is also responsible for making connections and maintaining connections. Any node whether they are a validator or non-validator will attempt to connect to the primary network.

Router

The ChainRouter routes all incoming messages to its respective blockchain using ChainID. It does this by pushing all the messages onto the respective Chain handler’s queue. The ChainRouter references all existing chains on the network such as the A-chain, D-chain, O-chain and possibly any other chain. The ChainRouter handles timeouts as well. When sending messages on the P2P layer, timeouts are registered on the sender and cleared on the ChainRouter side when a response is received. If no response is received, then we trigger a timeout. Because we handle timeouts on the ChainRouter side, the handler is reliable. Peers not responding means timeouts trigger and the ChainRouter will still notify the handler of failure cases. The timeout manager within ChainRouter is also adaptive. If the network is experiencing long latencies, timeouts will then be adjusted as well.

Handler

The main function of the Handler is to pass messages from the network to the consensus engine. It receives these messages from the ChainRouter. It passes messages by pushing them onto a sync or async queue (depends on message type). Messages are then popped from the queue, parsed, and routed to the correct function in consensus engine. This can be one of the following.

  • State sync message (sync queue)
  • Bootstrapping message (sync queue)
  • Consensus message (sync queue)
  • App message (async queue)

Sender

The main role of the sender is to build and send outbound messages. It is actually a very thin wrapper around the normal networking code. The main difference here is that sender registers timeouts and tells the [router] to expect a response message. The timer starts on the sender side. If there is no response, sender will send a failed response to the [router]. If a node is repeatedly unresponsive, that node will get benched and sender will immediately start marking those messages as failed. If a sufficient amount of network deems the node benched, it might not get rewards (as a validator).

Consensus Engine

Consensus is defined as getting a group of distributed systems to agree on an outcome. In the case of the Odyssey network, consensus is achieved when validators are in agreement with the state of the blockchain. There are two main consensus algorithms: Odyssey and Snowman. The engine is responsible for proposing a new block to consensus, repeatedly polling the network for decisions (accept/reject), and communicating that decision to the Sender.

Blockchain Creation

The Manager is what kickstarts everything in regards to blockchain creation, starting with the O-Chain. Once the O-Chain finishes bootstrapping, it will kickstart D-Chain and O-Chain and any other chain. The Manager’s job is not done yet, if a create chain transaction is seen by a validator, a whole new process to create a chain will be started by the Manager. This can happen dynamically, long after the original 3 chains are created and bootstrapped.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrUnknownState = errors.New("unknown state")

Functions

This section is empty.

Types

type Acceptor

type Acceptor interface {
	// Accept must be called before [containerID] is committed to the VM as
	// accepted.
	//
	// If the returned error is non-nil, the chain associated with [ctx] should
	// shut down and not commit [container] or any other container to its
	// database as accepted.
	Accept(ctx *ConsensusContext, containerID ids.ID, container []byte) error
}

Acceptor is implemented when a struct is monitoring if a message is accepted

type AcceptorGroup

type AcceptorGroup interface {
	// Calling Accept() calls all of the registered acceptors for the relevant
	// chain.
	Acceptor

	// RegisterAcceptor causes [acceptor] to be called every time an operation
	// is accepted on chain [chainID].
	// If [dieOnError], chain [chainID] stops if Accept returns a non-nil error.
	RegisterAcceptor(chainID ids.ID, acceptorName string, acceptor Acceptor, dieOnError bool) error

	// DeregisterAcceptor removes an acceptor from the group.
	DeregisterAcceptor(chainID ids.ID, acceptorName string) error
}

func NewAcceptorGroup

func NewAcceptorGroup(log logging.Logger) AcceptorGroup

type AcceptorTracker

type AcceptorTracker struct {
	// contains filtered or unexported fields
}

AcceptorTracker tracks the dispatched accept events by its ID and counts. Useful for testing.

func NewAcceptorTracker

func NewAcceptorTracker() *AcceptorTracker

func (*AcceptorTracker) Accept

func (a *AcceptorTracker) Accept(_ *ConsensusContext, containerID ids.ID, _ []byte) error

func (*AcceptorTracker) IsAccepted

func (a *AcceptorTracker) IsAccepted(containerID ids.ID) (int, bool)

type ConsensusContext

type ConsensusContext struct {
	*Context

	// Registers all common and snowman consensus metrics. Unlike the odyssey
	// consensus engine metrics, we do not prefix the name with the engine name,
	// as snowman is used for all chains by default.
	Registerer Registerer
	// Only used to register Odyssey consensus metrics. Previously, all
	// metrics were prefixed with "odyssey_{chainID}_". Now we add odyssey
	// to the prefix, "odyssey_{chainID}_odyssey_", to differentiate
	// consensus operations after the DAG linearization.
	OdysseyRegisterer Registerer

	// BlockAcceptor is the callback that will be fired whenever a VM is
	// notified that their block was accepted.
	BlockAcceptor Acceptor

	// TxAcceptor is the callback that will be fired whenever a VM is notified
	// that their transaction was accepted.
	TxAcceptor Acceptor

	// VertexAcceptor is the callback that will be fired whenever a vertex was
	// accepted.
	VertexAcceptor Acceptor

	// State indicates the current state of this consensus instance.
	State utils.Atomic[EngineState]

	// True iff this chain is executing transactions as part of bootstrapping.
	Executing utils.Atomic[bool]

	// True iff this chain is currently state-syncing
	StateSyncing utils.Atomic[bool]
}

func DefaultConsensusContextTest

func DefaultConsensusContextTest() *ConsensusContext

type Context

type Context struct {
	NetworkID uint32
	SubnetID  ids.ID
	ChainID   ids.ID
	NodeID    ids.NodeID
	PublicKey *bls.PublicKey

	AChainID     ids.ID
	DChainID     ids.ID
	DIONEAssetID ids.ID

	Log          logging.Logger
	Lock         sync.RWMutex
	Keystore     keystore.BlockchainKeystore
	SharedMemory atomic.SharedMemory
	FeeCollector feecollector.FeeCollector
	BCLookup     ids.AliaserReader
	Metrics      metrics.OptionalGatherer

	WarpSigner warp.Signer

	// snowman++ attributes
	ValidatorState validators.State // interface for O-Chain validators
	// Chain-specific directory where arbitrary data can be written
	ChainDataDir string
}

Context is information about the current execution. [NetworkID] is the ID of the network this context exists within. [ChainID] is the ID of the chain this context exists within. [NodeID] is the ID of this node

func DefaultContextTest

func DefaultContextTest() *Context

type ContextInitializable

type ContextInitializable interface {
	// InitCtx initializes an object provided a *Context object
	InitCtx(ctx *Context)
}

ContextInitializable represents an object that can be initialized given a *Context object

type EngineState

type EngineState struct {
	Type  p2p.EngineType
	State State
}

type Registerer

type Registerer interface {
	prometheus.Registerer
	prometheus.Gatherer
}

Expose gatherer interface for unit testing.

type State

type State uint8
const (
	Initializing State = iota
	StateSyncing
	Bootstrapping
	NormalOp
)

func (State) String

func (st State) String() string

Directories

Path Synopsis
consensus
snowman
Package snowman is a generated GoMock package.
Package snowman is a generated GoMock package.
engine
avalanche/state
Package state manages the meta-data required by consensus for an avalanche dag.
Package state manages the meta-data required by consensus for an avalanche dag.
avalanche/vertex
Package vertex is a generated GoMock package.
Package vertex is a generated GoMock package.
common
Package common is a generated GoMock package.
Package common is a generated GoMock package.
odyssey/state
Package state manages the meta-data required by consensus for an odyssey dag.
Package state manages the meta-data required by consensus for an odyssey dag.
odyssey/vertex
Package vertex is a generated GoMock package.
Package vertex is a generated GoMock package.
snowman/block/mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
networking
handler
Package handler is a generated GoMock package.
Package handler is a generated GoMock package.
router
Package router is a generated GoMock package.
Package router is a generated GoMock package.
sender
Package sender is a generated GoMock package.
Package sender is a generated GoMock package.
timeout
Package timeout is a generated GoMock package.
Package timeout is a generated GoMock package.
tracker
Package tracker is a generated GoMock package.
Package tracker is a generated GoMock package.
Package uptime is a generated GoMock package.
Package uptime is a generated GoMock package.
Package validators is a generated GoMock package.
Package validators is a generated GoMock package.

Jump to

Keyboard shortcuts

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