perun

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2020 License: Apache-2.0 Imports: 11 Imported by: 0

README

Perun Node - Go implementation

Develop Master
CircleCI CircleCI

Perun is an open source project that aims to increase blockchain transaction throughput by using just a handful of main chain transactions to move an entire peer-to-peer network of activity off the main chain. After an initial setup of a set of basic transaction channels, this network lets any participant transact with any other participant via virtual channels which do not require additional on-chain setup. We do this by implementing the Perun protocol, which has been formally proven to allow for secure off-chain transactions.

Project Status

At the moment the perun-node is neither ready for production nor does it implement the complete perun protocol yet. But with basic features available, the project is at a stage where you can try it out and start to get involved.

This is a complete re-implementation of the previous version (available under the previous name of the project: dst-go) in branch legacy/master. This version builds on top of the go-perun SDK that implements a state channel client based on perun protocol. See Description for more details.

Description

The perun-node is multi-user state channel node that can be used for opening, transacting on and closing state channels. It builds on the state channel client implemented by go-perun and implements the following functionalities:

  1. Payment App: For using perun protocol to establish and use bi-directional payment channels.
  2. Contacts Provider: For the user to define a list of known participants in the off-chain network.
  3. Key management: For managing the cryptographic keys of the user.
  4. User session: For allowing multiple users to use a single node, each with a dedicated key manager and contacts provider.
  5. User API interface: For the user to interact with the perun-node.

The current version provides the following features:

Feature Implementation
Blockchain Backend Ethereum
Key management Ethereum keystore
Contacts Provider YAML file
User API Two Party Payment API
User API Adapter gRPC

An example for a complete sequence of using the perun node can be found in the integration test in api/grpc package in server_integ_test.go. An independently running node binary is yet to be implemented and will be included in the next release.

Getting Started

Install the following pre-requisites.

1. Go (v1.14 or later).
2. ganache-cli (v6.9.1 or later).

Clone the project and sync the dependencies:

git clone https://github.com/hyperledger-labs/perun-node.git
cd perun-node
go mod tidy

Start the ganache-cli node for running integration tests:

# These funded accounts will be used in tests. "-b 1" configures the
# ganache-cli node to mine one block every second. It is required as our
# contracts use blockchain based timeout for settling a state channel on-chain.
ganache-cli -b 1 \
--account="0x1fedd636dbc7e8d41a0622a2040b86fea8842cef9d4aa4c582aad00465b7acff,100000000000000000000" \
--account="0xb0309c60b4622d3071fad3e16c2ce4d0b1e7758316c187754f4dd0cfb44ceb33,100000000000000000000"

Run the linter and tests from the project root directory:

# Lint
golangci-lint run ./...

# Test
go test -tags=integration -count=1 ./...

License

perun-node is open-sourced under the Apache-2.0 license. See the LICENSE file for details.

Documentation

Overview

Package perun defines the different types and backends in this project. Implementation of functionalities of the types and packges will be done in the corresponding packages.

Index

Constants

View Source
const OwnAlias = "self"

OwnAlias is the alias for the entry of the user's own peer details. It will be used when translating addresses in incoming messages / proposals to aliases.

Variables

View Source
var (
	ErrUnknownSessionID  = APIError("No session corresponding to the specified ID.")
	ErrUnknownProposalID = APIError("No channel proposal corresponding to the specified ID.")
	ErrUnknownChannelID  = APIError("No channel corresponding to the specified ID.")
	ErrUnknownAlias      = APIError("No peer corresponding to the specified ID was found in contacts.")
	ErrUnknownUpdateID   = APIError("No response was expected for the given channel update ID")

	ErrUnsupportedCurrency     = APIError("Currency not supported by this node instance.")
	ErrUnsupportedContactsType = APIError("Contacts type not supported by this node instance.")
	ErrUnsupportedCommType     = APIError("Communication protocol not supported by this node instance.")

	ErrInsufficientBal     = APIError("Insufficient balance in sender account.")
	ErrInvalidAmount       = APIError("Invalid amount string")
	ErrMissingBalance      = APIError("Missing balance")
	ErrInvalidConfig       = APIError("Invalid configuration detected.")
	ErrInvalidOffChainAddr = APIError("Invalid off-chain address string.")
	ErrInvalidPayee        = APIError("Invalid payee, no such participant in the channel.")

	ErrNoActiveSub      = APIError("No active subscription was found.")
	ErrSubAlreadyExists = APIError("A subscription for this context already exists.")

	ErrChFinalized        = APIError("Channel is finalized.")
	ErrChClosed           = APIError("Channel is closed.")
	ErrPeerAliasInUse     = APIError("Alias already used by another peer in the contacts.")
	ErrPeerExists         = APIError("Peer already available in the contacts provider.")
	ErrRespTimeoutExpired = APIError("Response to the notification was sent after the timeout has expired.")
	ErrPeerRejected       = APIError("The request was rejected by the peer.")

	ErrUnclosedCh     = APIError("Session cannot be closed (without force option as there are unclosed channels.")
	ErrInternalServer = APIError("Internal Server Error")
)

Sentinal Error values that are relevant for the end user of the node.

Functions

func GetAPIError

func GetAPIError(err error) error

GetAPIError returns the APIError contained in err if err is an APIError. If not, it returns ErrInternalServer API error.

Types

type APIError

type APIError string

APIError represents the errors that will be communicated via the user API.

func (APIError) Error

func (e APIError) Error() string

type App

type App struct {
	Def  pwallet.Address
	Data pchannel.Data
}

App represents the parameters of an App used in a channel.

type BalInfo

type BalInfo struct {
	Currency string
	Bals     map[string]string // Map of alias to balance.
}

BalInfo is used to send the balance information to the user.

type ChCloseNotif

type ChCloseNotif struct {
	ChannelID string
	Currency  string
	ChState   *pchannel.State
	Parts     []string
	Error     string
}

ChCloseNotif represents the parameters sent in a channel close notifications.

type ChCloseNotifier

type ChCloseNotifier func(ChCloseNotif)

ChCloseNotifier is the notifier function that is used for sending channel close notifications.

type ChProposalNotif

type ChProposalNotif struct {
	ProposalID string
	Currency   string
	Proposal   *pclient.ChannelProposal
	Parts      []string
	Expiry     int64
}

ChProposalNotif represents the parameters sent in a channel proposal notifications.

type ChProposalNotifier

type ChProposalNotifier func(ChProposalNotif)

ChProposalNotifier is the notifier function that is used for sending channel proposal notifications.

type ChUpdateNotif

type ChUpdateNotif struct {
	UpdateID  string
	Currency  string
	CurrState *pchannel.State
	Update    *pclient.ChannelUpdate
	Parts     []string
	Expiry    int64
}

ChUpdateNotif represents the parameters sent in a channel update notifications.

type ChUpdateNotifier

type ChUpdateNotifier func(ChUpdateNotif)

ChUpdateNotifier is the notifier function that is used for sending channel update notifications.

type ChainBackend

type ChainBackend interface {
	DeployAdjudicator() (adjAddr pwallet.Address, _ error)
	DeployAsset(adjAddr pwallet.Address) (assetAddr pwallet.Address, _ error)
	ValidateContracts(adjAddr, assetAddr pwallet.Address) error
	NewFunder(assetAddr pwallet.Address) pchannel.Funder
	NewAdjudicator(adjAddr, receiverAddr pwallet.Address) pchannel.Adjudicator
}

ChainBackend wraps the methods required for instantiating and using components for making on-chain transactions and reading on-chain values on a specific blockchain platform. The timeout for on-chain transaction should be implemented by the corresponding backend. It is upto the implementation to make the value user configurable.

It defines methods for deploying contracts; validating deployed contracts and instantiating a funder, adjudicator.

type ChannelAPI

type ChannelAPI interface {
	ID() string
	SendChUpdate(context.Context, StateUpdater) error
	SubChUpdates(ChUpdateNotifier) error
	UnsubChUpdates() error
	RespondChUpdate(context.Context, string, bool) error
	GetInfo() ChannelInfo
	Close(context.Context) (ChannelInfo, error)
}

ChannelAPI represents the APIs that can be accessed in the context of a perun channel. First a channel has to be initialized using the SessionAPI. The channel can then be used send and receive updates.

type ChannelClient

type ChannelClient interface {
	Registerer
	ProposeChannel(context.Context, *pclient.ChannelProposal) (*pclient.Channel, error)
	Handle(pclient.ProposalHandler, pclient.UpdateHandler)
	Channel(pchannel.ID) (*pclient.Channel, error)
	Close() error

	EnablePersistence(ppersistence.PersistRestorer)
	OnNewChannel(handler func(*pclient.Channel))
	Restore(context.Context) error

	Log() pLog.Logger
}

ChannelClient allows the user to establish off-chain channels and transact on these channels.

It allows the user to enable persistence, where all data pertaining to the lifecycle of a channel is persisted continuously. When it is enabled, the channel client can be stopped at any point of time and resumed later.

However, the channel client is not responsible if any channel the user was participating in was closed with a wrong state when the channel client was not running. Hence it is highly recommended not to stop the channel client if there are open channels.

type ChannelInfo

type ChannelInfo struct {
	ChannelID string
	Currency  string
	State     *pchannel.State
	Parts     []string // List of Alias of channel participants.
}

ChannelInfo represents the info regarding a channel that will be sent to the user.

type CommBackend

type CommBackend interface {
	// Returns a listener that can listen for incoming messages at the specified address.
	NewListener(address string) (pnet.Listener, error)

	// Returns a dialer that can dial for new outgoing connections.
	// If timeout is zero, program will use no timeout, but standard OS timeouts may still apply.
	NewDialer() Dialer
}

CommBackend defines the set of methods required for initializing components required for off-chain communication. This can be protocols such as tcp, websockets, MQTT.

type Contacts

type Contacts interface {
	ContactsReader
	Write(alias string, p Peer) error
	Delete(alias string) error
	UpdateStorage() error
}

Contacts represents a cached list of contacts backed by a storage. Read, Write and Delete methods act on the cache. The state of cached list can be written to the storage by using the UpdateStorage method.

type ContactsReader

type ContactsReader interface {
	ReadByAlias(alias string) (p Peer, contains bool)
	ReadByOffChainAddr(offChainAddr pwire.Address) (p Peer, contains bool)
}

ContactsReader represents a read only cached list of contacts.

type Credential

type Credential struct {
	Addr     pwallet.Address
	Wallet   pwallet.Wallet
	Keystore string
	Password string
}

Credential represents the parameters required to access the keys and make signatures for a given address.

type Currency

type Currency interface {
	Parse(string) (*big.Int, error)
	Print(*big.Int) string
}

Currency represents a parser that can convert between string representation of a currency and its equivalent value in base unit represented as a big interger.

type Dialer

type Dialer interface {
	pnet.Dialer
	Registerer
}

Dialer extends net.Dialer with Registerer interface.

type NodeAPI

type NodeAPI interface {
	Time() int64
	GetConfig() NodeConfig
	Help() []string
	OpenSession(configFile string) (string, error)

	// This function is used internally to get a SessionAPI instance.
	// Should not be exposed via userAPI.
	GetSession(string) (SessionAPI, error)
}

NodeAPI represents the APIs that can be accessed in the context of a perun node. Multiple sessions can be opened in a single node. Each instance will have a dedicated keystore and contacts provider.

type NodeConfig

type NodeConfig struct {
	LogLevel string // LogLevel represents the log level for the node and all dervied loggers.
	LogFile  string // LogFile represents the file to write logs. Empty string represents stdout.

	ChainURL     string   // Address of the default blockchain node used by the perun node.
	Adjudicator  string   // Address of the default Adjudicator contract used by the perun node.
	Asset        string   // Address of the default Asset Holder contract used by the perun node.
	CommTypes    []string // Communication protocols supported by the node for off-chain communication.
	ContactTypes []string // Contacts Provider backends supported by the node.
	Currencies   []string // Currencies supported by the node.

	ChainConnTimeout time.Duration // Timeout for connecting to blockchain node.
	OnChainTxTimeout time.Duration // Timeout to wait for confirmation of on-chain tx.
	ResponseTimeout  time.Duration // Timeout to wait for a response from the peer / user.
}

NodeConfig represents the configurable parameters of a perun node.

type Peer

type Peer struct {
	// Name assigned by user for referring to this peer in api requests to the node.
	// It is unique within a session on the node.
	Alias string `yaml:"alias"`

	// Permanent identity used for authenticating the peer in the off-chain network.
	OffChainAddr pwire.Address `yaml:"-"`
	// This field holds the string value of address for easy marshaling / unmarshaling.
	OffChainAddrString string `yaml:"offchain_address"`

	// Address for off-chain communication.
	CommAddr string `yaml:"comm_address"`
	// Type of off-chain communication protocol.
	CommType string `yaml:"comm_type"`
}

Peer represents any participant in the off-chain network that the user wants to transact with.

type Registerer

type Registerer interface {
	Register(offChainAddr pwire.Address, commAddr string)
}

Registerer is used to register the commAddr corresponding to an offChainAddr to the wire.Bus in runtime.

type Session

type Session struct {
	ID   string // ID uniquely identifies a session instance.
	User User

	ChannelClient ChannelClient
}

Session provides a context for the user to interact with a node. It manages user data (such as IDs, contacts), and channel client.

Once established, a user can establish and transact on state channels. All the channels within a session will use the same type and version of communication and state channel protocol. If a user desires to use multiple types or versions of any protocol, it should request a seprate session for each combination of type and version of those.

type SessionAPI

type SessionAPI interface {
	ID() string
	AddContact(Peer) error
	GetContact(alias string) (Peer, error)
	OpenCh(context.Context, string, BalInfo, App, uint64) (ChannelInfo, error)
	HandleClose(string, error)
	GetChInfos() []ChannelInfo
	HandleUpdate(pclient.ChannelUpdate, *pclient.UpdateResponder)
	HandleProposal(*pclient.ChannelProposal, *pclient.ProposalResponder)
	SubChProposals(ChProposalNotifier) error
	UnsubChProposals() error
	RespondChProposal(context.Context, string, bool) error
	SubChCloses(ChCloseNotifier) error
	UnsubChCloses() error

	// This function is used internally to get a ChannelAPI instance.
	// Should not be exposed via userAPI.
	GetCh(string) (ChannelAPI, error)
}

SessionAPI represents the APIs that can be accessed in the context of a perun node. First a session has to be instantiated using the NodeAPI. The session can then be used open channels and accept channel proposals.

type StateUpdater

type StateUpdater func(*pchannel.State)

StateUpdater function is the function that will be used for applying state updates.

type User

type User struct {
	Peer

	OnChain  Credential // Account for funding the channel and the on-chain transactions.
	OffChain Credential // Account (corresponding to off-chain address) used for signing authentication messages.

	// List of participant addresses for this user in each open channel.
	// OffChain credential is used for managing all these accounts.
	PartAddrs []pwallet.Address
}

User represents a participant in the off-chain network that uses a session on this node for sending transactions.

type WalletBackend

type WalletBackend interface {
	ParseAddr(string) (pwallet.Address, error)
	NewWallet(keystore string, password string) (pwallet.Wallet, error)
	UnlockAccount(pwallet.Wallet, pwallet.Address) (pwallet.Account, error)
}

WalletBackend wraps the methods for instantiating wallets and accounts that are specific to a blockchain platform.

type WireBus

type WireBus interface {
	pwire.Bus
	Close() error
}

WireBus is a an extension of the wire.Bus interface in go-perun to include a "Close" method. pwire.Bus (in go-perun) is a central message bus over which all clients of a channel network communicate. It is used as the transport layer abstraction for the ChannelClient.

Directories

Path Synopsis
api
grpc
Package grpc implements a grpc payment API server.
Package grpc implements a grpc payment API server.
grpc/pb
Package pb contains proto3 definitions for user API and the corresponding generated code for grpc server and client.
Package pb contains proto3 definitions for user API and the corresponding generated code for grpc server and client.
app
payment
Package payment implements a payment API that can used with the generic session and channel APIs to open, use and close payment channels.
Package payment implements a payment API that can used with the generic session and channel APIs to open, use and close payment channels.
blockchain
ethereum
Package ethereum provides on-chain transaction backend and wallet backend for the ethereum blockchain platform.
Package ethereum provides on-chain transaction backend and wallet backend for the ethereum blockchain platform.
ethereum/ethereumtest
Package ethereumtest provides test helpers for using ethereum backend in test.
Package ethereumtest provides test helpers for using ethereum backend in test.
ethereum/internal
Package internal implements the ethereum related backend functionality.
Package internal implements the ethereum related backend functionality.
Package client provides an abstraction over the channel client used for running the off-chain network implemented by go-perun project.
Package client provides an abstraction over the channel client used for running the off-chain network implemented by go-perun project.
cmd
perunnode
Package perunnode implements the perun node API.
Package perunnode implements the perun node API.
comm
tcp
Package tcp implements the off-chain communication backend to initialize adapters for for tcp communication protocol.
Package tcp implements the off-chain communication backend to initialize adapters for for tcp communication protocol.
contacts
contactstest
Package contactstest provides a helper functions to create contacts file from a list of peers for use in tests.
Package contactstest provides a helper functions to create contacts file from a list of peers for use in tests.
contactsyaml
Package contactsyaml implements contacts provider to access contacts stored in a yaml file.
Package contactsyaml implements contacts provider to access contacts stored in a yaml file.
Package currency implements conversion backends for different currencies used in a channel.
Package currency implements conversion backends for different currencies used in a channel.
internal
Package log implements a simple logger that directly uses the logrus library.
Package log implements a simple logger that directly uses the logrus library.
Package session implements a session to which a user can attach his or her credentials.
Package session implements a session to which a user can attach his or her credentials.
sessiontest
Package sessiontest implements test helpers for functionalities defined in session.
Package sessiontest implements test helpers for functionalities defined in session.

Jump to

Keyboard shortcuts

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