weave

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2018 License: Apache-2.0 Imports: 14 Imported by: 0

README

Confio Weave

Build Status circleCI API Reference license LoC Go Report Card

Confio Weave is a framework for quickly building your custom ABCI application to run a blockchain on top of the best-of-class BFT Proof-of-stake Tendermint consensus engine. It provides much commonly used functionality that can quickly be imported in your custom chain, as well as a simple framework for adding the custom functionality unique to your project.

Note: Requires Go 1.9+

It is inspired by the routing and middleware model of many web application frameworks, and informed by years of wrestling with blockchain state machines. More directly, it is based on the offical cosmos-sdk, both the 0.8 release as well as the future 0.9 rewrite. Naturally, as I was the main author of 0.8.

While both of those are extremely powerful and flexible and contain advanced features, they have a steep learning curve for novice users. Thus, this library aims to favor simplicity over power when there is a choice. If you hit limitations in the design of this library (such as maintaining multiple merkle stores in one app), I highly advise you to use the official cosmos sdk.

On the other hand, if you want to try out tendermint, or have a design that doesn't require an advanced setup, you should try this library and give feedback, especially on ease-of-use. The end goal is to make blockchain development almost as productive as web development (in golang), by providing defaults and best practices for many choices, while allowing extreme flexibility in business logic and data modelling.

For more details on the design goals, see the Design Document

Prerequisites

Instructions

How to build and run a simple app:

# this installs all vendor dependencies, as well as the
# tendermint binary
make deps
make install

# initialize an app
tendermint init --home $HOME/.mycoind
mycoind init  # adds app-specific options

# run the app
tendermint node --home $HOME/.mycoind > /tmp/tendermint.log &
mycoind start

Note that this app relies on a separate tendermint process to drive it. It is helpful to first read a primer on tendermint as well as the documentation on the tendermint cli commands.

Documentation

Overview

We pass context through context.Context between app, middleware, and handlers. To do so, weave defines some common keys to store info, such as block height and chain id. Each extension, such as auth, may add its own keys to enrich the context with specific data.

There should exist two functions for every XYZ of type T that we want to support in Context:

WithXYZ(Context, T) Context
GetXYZ(Context) (val T, ok bool)

WithXYZ may error/panic if the value was previously set to avoid lower-level modules overwriting the value (eg. height, header)

Index

Constants

View Source
const Fix = 0
View Source
const Maj = 0

Note: update VersionTest when changing the version

View Source
const Min = 1
View Source
const Suffix = ""

Suffix used when not a tagged release (eg. -dev, -alpha, -beta, etc)

Variables

View Source
var (
	// Default logger is used for all context that have not
	// set anything themselves
	DefaultLogger = log.NewNopLogger()

	// IsValidChainID is the RegExp to ensure valid chain IDs
	IsValidChainID = regexp.MustCompile(`^[a-zA-Z0-9_\-]{6,20}$`).MatchString
)
View Source
var (
	// AddressLength is the length of all addresses
	// You can modify it in init() before any addresses are calculated,
	// but it must not change during the lifetime of the kvstore
	AddressLength = 20
)
View Source
var GitCommit = ""

GitCommit set by build flags

Functions

func CheckOrError

func CheckOrError(result CheckResult, err error) abci.ResponseCheckTx

CheckOrError returns an abci response for CheckTx, converting the error message if present, or using the successful CheckResult

func CheckTxError

func CheckTxError(err error) abci.ResponseCheckTx

CheckTxError converts any error into a abci.ResponseCheckTx, preserving as much info as possible if it was already a TMError

func DeliverOrError

func DeliverOrError(result DeliverResult, err error) abci.ResponseDeliverTx

DeliverOrError returns an abci response for DeliverTx, converting the error message if present, or using the successful DeliverResult

func DeliverTxError

func DeliverTxError(err error) abci.ResponseDeliverTx

DeliverTxError converts any error into a abci.ResponseDeliverTx, preserving as much info as possible if it was already a TMError

func GetChainID

func GetChainID(ctx Context) string

GetChainID returns the current chain id panics if chain id not already set (should never happen)

func GetHeader

func GetHeader(ctx Context) (abci.Header, bool)

GetHeader returns the current block header ok is false if no header set in this Context

func GetHeight

func GetHeight(ctx Context) (int64, bool)

GetHeight returns the current block height ok is false if no height set in this Context

func GetLogger

func GetLogger(ctx Context) log.Logger

GetLogger returns the currently set logger, or DefaultLogger if none was set

func GetPath

func GetPath(tx Tx) string

GetPath returns the path of the message, or (missing) if no message

func HasAllSigners

func HasAllSigners(required []Address, signed []Address) bool

HasAllSigners returns true if all elements in required are also in signed.

func HasNSigners

func HasNSigners(n int, requested []Address, signed []Address) bool

HasNSigners returns true if at least n elements in requested are also in signed. Useful for threshold conditions (1 of 3, 3 of 5, etc...)

func HasSigner

func HasSigner(required Address, signed []Address) bool

HasSigner returns true if this address has signed

func MustMarshal

func MustMarshal(obj Marshaller) []byte

MustMarshal will succeed or panic

func MustMarshalValid

func MustMarshalValid(obj MarshalValidater) []byte

MustMarshalValid marshals the object, but panics if the object is not valid or has trouble marshalling

func MustUnmarshal

func MustUnmarshal(obj Persistent, bz []byte)

MustUnmarshal will succeed or panic

func MustValidate

func MustValidate(obj Validater)

MustValidate panics if the object is not valid

func Version

func Version() string

Version is the string to be displayed

Types

type Address

type Address []byte

Address represents a collision-free, one-way digest of data (usually a public key) that can be used to identify a signer

It will be of size AddressLength

func MainSigner

func MainSigner(ctx Context, fn AuthFunc) Address

MainSigner returns the first signed if any, otherwise nil

func MustObjAddress

func MustObjAddress(obj Marshaller) Address

MustObjAddress is like ObjAddress, but panics instead of returning errors. Only use when you control the obj being passed in.

func NewAddress

func NewAddress(data []byte) Address

NewAddress hashes and truncates into the proper size

func ObjAddress

func ObjAddress(obj Marshaller) (Address, error)

ObjAddress takes the address of an object

func (Address) MarshalJSON

func (a Address) MarshalJSON() ([]byte, error)

func (*Address) UnmarshalJSON

func (a *Address) UnmarshalJSON(src []byte) error

type AuthFunc

type AuthFunc func(Context) []Address

AuthFunc is a function we can use to extract authentication info from the context. This should be passed into the constructor of handlers, so we can plug in another authentication system, rather than hardcoding x/auth for all extensions.

func MultiAuth

func MultiAuth(fns ...AuthFunc) AuthFunc

type Batch

type Batch interface {
	SetDeleter
	Write()
}

Batch can write multiple ops atomically to an underlying KVStore

type CacheableKVStore

type CacheableKVStore interface {
	KVStore
	CacheWrap() KVCacheWrap
}

CacheableKVStore is a KVStore that supports CacheWrapping

CacheWrap() should not return a Committer, since Commit() on cache-wraps make no sense.

type CheckResult

type CheckResult struct {
	Data data.Bytes
	Log  string
	// GasAllocated is the maximum units of work we allow this tx to perform
	GasAllocated int64
	// GasPayment is the total fees for this tx (or other source of payment)
	GasPayment int64
}

CheckResult captures any non-error abci result to make sure people use error for error cases

func NewCheck

func NewCheck(gasAllocated int64, log string) CheckResult

NewCheck sets the gas used and the response data but no more info these are the most common info needed to be set by the Handler

func (CheckResult) ToABCI

func (c CheckResult) ToABCI() abci.ResponseCheckTx

ToABCI converts our internal type into an abci response

type Checker

type Checker interface {
	Check(ctx Context, store KVStore, tx Tx) (CheckResult, error)
}

Checker is a subset of Handler to verify the validity of a transaction. It is its own interface to allow better type controls in the next arguments in Decorator

type CommitID

type CommitID struct {
	Version int64
	Hash    []byte
}

CommitID contains the tree version number and its merkle root.

type CommitKVStore

type CommitKVStore interface {
	// Get returns the value at last committed state
	// returns nil iff key doesn't exist. Panics on nil key.
	Get(key []byte) []byte

	// Get a CacheWrap to perform actions
	// TODO: add Batch to atomic writes and efficiency
	// invisibly inside this CacheWrap???
	CacheWrap() KVCacheWrap

	// Commit the next version to disk, and returns info
	Commit() CommitID

	// LoadLatestVersion loads the latest persisted version.
	// If there was a crash during the last commit, it is guaranteed
	// to return a stable state, even if older.
	LoadLatestVersion() error

	// LatestVersion returns info on the latest version saved to disk
	LatestVersion() CommitID
}

type Context

type Context = context.Context

Context is just an alias for the standard implementation. We use functions to extend it to our domain

func WithChainID

func WithChainID(ctx Context, chainID string) Context

WithChainID sets the chain id for the Context. panics if called with chain id already set

func WithHeader

func WithHeader(ctx Context, header abci.Header) Context

WithHeader sets the block header for the Context. panics if called with header already set

func WithHeight

func WithHeight(ctx Context, height int64) Context

WithHeight sets the block height for the Context. panics if called with height already set

func WithLogInfo

func WithLogInfo(ctx Context, keyvals ...interface{}) Context

WithLogInfo accepts keyvalue pairs, and returns another context like this, after passing all the keyvals to the Logger

func WithLogger

func WithLogger(ctx Context, logger log.Logger) Context

WithLogger sets the logger for this Context

type Decorator

type Decorator interface {
	Check(ctx Context, store KVStore, tx Tx, next Checker) (CheckResult, error)
	Deliver(ctx Context, store KVStore, tx Tx, next Deliverer) (DeliverResult, error)
}

Decorator wraps a Handler to provide common functionality like authentication, or fee-handling, to many Handlers

type DeliverResult

type DeliverResult struct {
	Data    data.Bytes
	Log     string
	Diff    []abci.Validator
	Tags    []common.KVPair
	GasUsed int64 // unused
}

DeliverResult captures any non-error abci result to make sure people use error for error cases

func (DeliverResult) ToABCI

ToABCI converts our internal type into an abci response

type Deliverer

type Deliverer interface {
	Deliver(ctx Context, store KVStore, tx Tx) (DeliverResult, error)
}

Checker is a subset of Handler to execute a transaction. It is its own interface to allow better type controls in the next arguments in Decorator

type Handler

type Handler interface {
	Checker
	Deliverer
}

Handler is a core engine that can process a few specific messages This could represent "coin transfer", or "bonding stake to a validator"

type Initializer

type Initializer interface {
	FromGenesis(Options, KVStore) error
}

Initializer implementations are used to initialize extensions from genesis file contents

type Iterator

type Iterator interface {
	// Valid returns whether the current position is valid.
	// Once invalid, an Iterator is forever invalid.
	Valid() bool

	// Next moves the iterator to the next sequential key in the database, as
	// defined by order of iteration.
	//
	// If Valid returns false, this method will panic.
	Next()

	// Key returns the key of the cursor.
	// If Valid returns false, this method will panic.
	// CONTRACT: key readonly []byte
	Key() (key []byte)

	// Value returns the value of the cursor.
	// If Valid returns false, this method will panic.
	// CONTRACT: value readonly []byte
	Value() (value []byte)

	// Close releases the Iterator.
	Close()
}

Iterator allows us to access a set of items within a range of keys. These may all be preloaded, or loaded on demand.

Usage:

var itr Iterator = ...
defer itr.Close()

for ; itr.Valid(); itr.Next() {
  k, v := itr.Key(); itr.Value()
  // ...
}

type KVCacheWrap

type KVCacheWrap interface {
	// CacheableKVStore allows us to use this Cache recursively
	CacheableKVStore

	// Write syncs with the underlying store.
	Write()

	// Discard invalidates this CacheWrap and releases all data
	Discard()
}

KVCacheWrap allows us to maintain a scratch-pad of uncommitted data that we can view with all queries.

At the end, call Write to use the cached data, or Discard to drop it.

type KVStore

type KVStore interface {
	ReadOnlyKVStore
	SetDeleter
	// NewBatch returns a batch that can write multiple ops atomically
	NewBatch() Batch
}

KVStore is a simple interface to get/set data

For simplicity, we require all backing stores to implement this interface. They *may* implement other methods as well, but at least these are required.

type MarshalValidater

type MarshalValidater interface {
	Marshaller
	Validater
}

type Marshaller

type Marshaller interface {
	Marshal() ([]byte, error)
}

Marshaller is anything that can be represented in binary

Marshall may validate the data before serializing it and unless you previously validated the struct, errors should be expected.

type Msg

type Msg interface {
	Persistent

	// Return the message path.
	// This is used by the Router to locate the proper Handler.
	// Msg should be created alongside the Handler that corresponds to them.
	//
	// Multiple types may have the same value, and will end up at the
	// same Handler.
	//
	// Must be alphanumeric [0-9A-Za-z_\-]+
	Path() string
}

Msg is message for the blockchain to take an action (Make a state transition). It is just the request, and must be validated by the Handlers. All authentication information is in the wrapping Tx.

type Options

type Options map[string]json.RawMessage

Options are the app options Each extension can look up it's key and parse the json as desired

func (Options) ReadOptions

func (o Options) ReadOptions(key string, obj interface{}) error

ReadOptions reads the values stored under a given key, and parses the json into the given obj. Returns an error if it cannot parse. Noop and no error if key is missing

type Persistent

type Persistent interface {
	Marshaller
	Unmarshal([]byte) error
}

Persistent supports Marshal and Unmarshal

This is separated from Marshal, as this almost always requires a pointer, and functions that only need to marshal bytes can use the Marshaller interface to access non-pointers.

As with Marshaller, this may do internal validation on the data and errors should be expected.

type ReadOnlyKVStore

type ReadOnlyKVStore interface {
	// Get returns nil iff key doesn't exist. Panics on nil key.
	Get(key []byte) []byte

	// Has checks if a key exists. Panics on nil key.
	Has(key []byte) bool

	// Iterator over a domain of keys in ascending order. End is exclusive.
	// Start must be less than end, or the Iterator is invalid.
	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
	Iterator(start, end []byte) Iterator

	// ReverseIterator over a domain of keys in descending order. End is exclusive.
	// Start must be greater than end, or the Iterator is invalid.
	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
	ReverseIterator(start, end []byte) Iterator
}

ReadOnlyKVStore is a simple interface to query data.

type Registry

type Registry interface {
	Handle(path string, h Handler)
}

Registry is an interface to register your handler, the setup side of a Router

type SetDeleter

type SetDeleter interface {
	Set(key, value []byte) // CONTRACT: key, value readonly []byte
	Delete(key []byte)     // CONTRACT: key readonly []byte
}

SetDeleter is a minimal interface for writing, Unifying KVStore and Batch

type TickResult

type TickResult struct {
	Diff []abci.Validator
}

TickResult allows the Ticker to modify the validator set

type Ticker

type Ticker interface {
	Tick(ctx Context, store KVStore) (TickResult, error)
}

Ticker is a method that is called the beginning of every block, which can be used to perform periodic or delayed tasks

type Tx

type Tx interface {
	// GetMsg returns the action we wish to communicate
	GetMsg() (Msg, error)
}

Tx represent the data sent from the user to the chain. It includes the actual message, along with information needed to authenticate the sender (cryptographic signatures), and anything else needed to pass through middleware.

Each Application must define their own tx type, which embeds all the middlewares that we wish to use. auth.SignedTx and token.FeeTx are common interfaces that many apps will wish to support.

type TxDecoder

type TxDecoder func(txBytes []byte) (Tx, error)

TxDecoder can parse bytes into a Tx

type Validater

type Validater interface {
	Validate() error
}

Validater is any struct that can be validated. Not the same as a Validator, which votes on the blocks.

Directories

Path Synopsis
cmd
mycoind command
commands
Package crypto is a generated protocol buffer package.
Package crypto is a generated protocol buffer package.
nolint
nolint
Package std contains standard implementations of a number of components.
Package std contains standard implementations of a number of components.
nolint
nolint
x
Extensions All sub-packages are various extensions, useful to build applications, but not necessary to use the framework.
Extensions All sub-packages are various extensions, useful to build applications, but not necessary to use the framework.
auth
Package auth is a generated protocol buffer package.
Package auth is a generated protocol buffer package.
coins
Package coins is a generated protocol buffer package.
Package coins is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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