app

package
v1.10.1 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2024 License: Apache-2.0 Imports: 20 Imported by: 2

README

meta.app: Generic ABCI application implementation

All of Oneiro's blockchains are implemented in terms of Tendermint's ABCI interface specification. There's actually a fair amount of busywork involved in satisfying that interface.

The purpose of this package is to abstract that interface's implementation.

Usage Checklist

  • subclass the meta-application:

    import meta "github.com/ndau/metanode/pkg/meta/app"
    type MyApp struct {
        *meta.App
        ...
    }
    
  • implement backing state conforming to the State interface.

  • implement some number of transactions conforming to the metatx.Transactable interface

  • construct a metatx.TxIDMap enumerating all valid Transactables

  • initialize your application as follows:

    func NewApp(...) (*MyApp, error) {
        metaapp, err := meta.NewApp(dbSpec, name, new(MyState), TxIDs)
        if err != nil {
            return nil, errors.Wrap(err, "NewApp failed to create metaapp")
        }
    
        // init your app's fields here
    
        app := App{
            metaapp,
            ...
        }
        app.App.SetChild(&app)
        return &app, nil
    }
    

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewLogger

func NewLogger() log.FieldLogger

NewLogger creates a new logger with default configuration, some of which can be overridden from environment variables. Callers should set up node_id and bin fields on the returned logger.

func RegisterQueryHandler

func RegisterQueryHandler(endpoint string, handler func(app interface{}, request abci.RequestQuery, response *abci.ResponseQuery))

RegisterQueryHandler registers a query handler at a particular endpoint

Types

type App

type App struct {
	abci.BaseApplication

	// List of pending validator updates
	ValUpdates []abci.ValidatorUpdate
	// contains filtered or unexported fields
}

App is an ABCI application which implements an Oneiro chain

func NewApp

func NewApp(dbSpec string, name string, childState metast.State, txIDs metatx.TxIDMap) (*App, error)

NewApp prepares a new App

  • `dbSpec` is the database spec string; empty or "mem" for in-memory, the connection path (parseable by noms)
  • `name` is the name of this app
  • `childState` is the child state manager. It must be initialized to its zero value.
  • `txIDs` is the map of transaction ids to example structs

func NewAppWithLogger

func NewAppWithLogger(dbSpec string, name string, childState metast.State, txIDs metatx.TxIDMap, logger log.FieldLogger) (*App, error)

NewAppWithLogger prepares a new App

  • `dbSpec` is the database spec string; empty or "mem" for in-memory, the connection path (parseable by noms)
  • `name` is the name of this app
  • `childState` is the child state manager. It must be initialized to its zero value.
  • `txIDs` is the map of transaction ids to example structs

func (*App) BeginBlock

func (app *App) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginBlock

BeginBlock tracks the block hash and header information

func (*App) BlockTime

func (app *App) BlockTime() math.Timestamp

BlockTime returns the timestamp of the current block

Note that this can lag fairly significantly behind real time; the only upper bound to the lag is the empty block creation rate. As of early 2019, the empty block creation rate is 5 minutes, so we expect to see BlockTime up to five minutes behind real time. This is due to Tendermint's block model and can't be fixed by our code.

func (*App) CheckTx

func (app *App) CheckTx(request abci.RequestCheckTx) (response abci.ResponseCheckTx)

CheckTx validates a Transaction

func (*App) Close

func (app *App) Close() error

Close closes the database connection opened on App creation

func (*App) Commit

func (app *App) Commit() abci.ResponseCommit

Commit saves a new version

Panics if InitChain has not been called.

func (*App) DecoratedLogger

func (app *App) DecoratedLogger() *log.Entry

DecoratedLogger returns a logger decorated with standard app data

func (*App) DecoratedTxLogger

func (app *App) DecoratedTxLogger(tx metatx.Transactable) *log.Entry

DecoratedTxLogger returns a logger decorated with the tx hash

func (*App) Defer

func (app *App) Defer(thunks ...Thunk)

Defer state-modification thunk(s) for application only if the rest of the tx's application succeeds.

func (*App) DeliverTx

func (app *App) DeliverTx(request abci.RequestDeliverTx) (response abci.ResponseDeliverTx)

DeliverTx services DeliverTx requests

func (*App) EndBlock

func (app *App) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock

EndBlock updates the validator set

func (*App) GetDB

func (app *App) GetDB() datas.Database

GetDB returns the app's database

func (*App) GetDS

func (app *App) GetDS() datas.Dataset

GetDS returns the app's dataset

func (*App) GetLogger

func (app *App) GetLogger() log.FieldLogger

GetLogger returns the application logger

func (*App) GetName

func (app *App) GetName() string

GetName returns the name of the app

func (*App) GetSearch

func (app *App) GetSearch() IncrementalIndexer

GetSearch returns the app's incremental indexer

func (*App) GetState

func (app *App) GetState() metast.State

GetState returns the current application state

func (*App) GetStats

func (app *App) GetStats() metast.VoteStats

GetStats returns node voting statistics.

This is typically used to update node goodness / voting power.

func (*App) Hash

func (app *App) Hash() []byte

Hash returns the current hash of the dataset

func (*App) HashStr

func (app *App) HashStr() string

HashStr returns the current hash of the dataset, encoded as a hexadecimal string.

This is useful because Tendermint expects hexadecimal encoding for hash strings, but noms by default uses its own sui-generis format: the first 20 bytes of big-endian base32 encoding.

func (*App) Height

func (app *App) Height() uint64

Height returns the current height of the application

func (*App) Info

func (app *App) Info(req abci.RequestInfo) (resInfo abci.ResponseInfo)

Info services Info requests

func (*App) InitChain

func (app *App) InitChain(req abci.RequestInitChain) (response abci.ResponseInitChain)

InitChain performs necessary chain initialization.

This includes saving the initial validator set in the local state.

func (*App) LogState

func (app *App) LogState()

LogState emits a log message detailing the current app state

func (*App) Query

func (app *App) Query(request abci.RequestQuery) (response abci.ResponseQuery)

Query determines the current value for a given key

func (*App) QueryError

func (app *App) QueryError(err error, response *abci.ResponseQuery, msg string)

QueryError is a helper to generate a useful response if an error is not nil

func (*App) SetChild

func (app *App) SetChild(child interface{})

SetChild specifies which child app is using this meta.App.

It is required to be called exactly once, during program initialization. It is not part of the normal constructor to ensure that it is possible to call NewApp within the constructor of the child.

func (*App) SetHeight

func (app *App) SetHeight(h uint64)

SetHeight updates the app's tendermint height

Under normal circumstances, this should never be called by a child application. Tendermint heights are automatically adjusted appropriately by the metaapp. This function is public so that test fixtures can be constructed with appropriate application heights.

func (*App) SetLogger

func (app *App) SetLogger(logger log.FieldLogger)

SetLogger sets the logger to be used by this app.

func (*App) SetOption

func (app *App) SetOption(request abci.RequestSetOption) (response abci.ResponseSetOption)

SetOption sets application options, but is entirely undocumented Note - Vle: The method has been removed from the ABCI.Client interface from tendermint version 0.35

func (*App) SetSearch

func (app *App) SetSearch(search IncrementalIndexer)

SetSearch sets the app's incremental indexer

func (*App) SetStateValidity

func (a *App) SetStateValidity(err error)

SetStateValidity will prevent further action by this node until the state error has cleared if a non-nil error is submitted.

Specifically, it will refuse to answer any queries, or validate any transactions.

func (*App) UpdateState

func (app *App) UpdateState(updaters ...func(state metast.State) (metast.State, error)) error

UpdateState updates the current child application state

Returning a nil state from the internal function is an error. Returning an error from the internal function returns that error.

func (*App) UpdateStateImmediately

func (app *App) UpdateStateImmediately(updaters ...func(state metast.State) (metast.State, error)) error

UpdateStateImmediately is like UpdateState, but commits immediately.

It also increments the height offset.

This is useful for inserting mock data etc.

func (*App) UpdateStateLeaky

func (app *App) UpdateStateLeaky(updaters ...func(state metast.State) (metast.State, error)) error

UpdateStateLeaky updates the child application state whether or not the internal updaters fail

This is buggy behavior and this function should NEVER be called in ordinary usage. However, we've got a running blockchain for which playback depends on replicating past bugs, so we have to be able to choose the old behavior.

func (*App) UpdateValidator

func (app *App) UpdateValidator(v abci.ValidatorUpdate)

UpdateValidator updates the app's internal state with the given validator

func (*App) Validators

func (app *App) Validators() ([]abci.Validator, error)

Validators returns a list of the app's validators.

func (*App) WatchSignals

func (app *App) WatchSignals()

WatchSignals starts a goroutine exits the app gracefully when SIGTERM or SIGINT is received.

type IncrementalIndexer

type IncrementalIndexer interface {
	OnBeginBlock(height uint64, blockTime math.Timestamp, tmHash string) error

	// OnDeliverTx is called only after the tx has been successfully applied
	OnDeliverTx(app interface{}, tx metatx.Transactable) error

	OnCommit() error
}

IncrementalIndexer declares methods for incremental indexing.

type Thunk

type Thunk func(metast.State) metast.State

A Thunk is a unit of computation prepared in one place and executed in another. It turns out that we need to be able to register and playback thunks, because it is important all of a transaction's state updates are applied atomically: if any of them fail, none are applied. What we'd ideally want is to change definition of `metatx.Apply` from

Apply(app interface{}) error

to

Apply(app interface{}) ([]func(metast.State) (metast.State, error), error)

while simultaneously deprecating `UpdateState`, eliminating it from node code. The result of this change would be that we could ensure that all state updates happened automatically and atomically: each tx application would simply return a list of thunks, and the state changes from each would be persisted if all thunks returned without error.

We can't do that: our blockchain's history includes some transactions for which a previously buggy implementation leaked state deltas despite the tx overall failing. Changing the interface in that way would preclude our feature-gated workaround, which imposes correct behavior in the future while ensuring that playback proceeds properly for those older blocks.

Instead, we have to settle for a somewhat worse solution. It accomplishes more or less the same thing, just in a more complicated, somewhat harder- to-use way. We can register deferred thunks. Each tx may still call UpdateState exactly once, but it may also register an arbitrary number of thunks. If the tx.Apply call succeeds, these thunks will be played back sequentially, further updating the application state.

However, these deferred thunks have more stringent restrictions than normal state updaters. They may not error, and they may not return nil. They have to succeed in all cases.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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