channel

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2024 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Overview

Package channel contains the Ethereum channel backend implementation.

Index

Constants

This section is empty.

Variables

View Source
var (
	// SharedExpectedNonces is a map of each expected next nonce of all clients.
	SharedExpectedNonces map[ChainID]map[common.Address]uint64
	// SharedExpectedNoncesMutex is a mutex to protect the shared expected nonces map.
	SharedExpectedNoncesMutex = &sync.Mutex{}
)
View Source
var ErrInvalidContractCode = stderrors.New("invalid bytecode at address")

ErrInvalidContractCode signals invalid bytecode at given address, such as incorrect or no code.

View Source
var ErrTxFailed = stderrors.New("transaction failed")

ErrTxFailed signals a failed, i.e., reverted, transaction.

View Source
var (

	// MaxBalance is the maximum amount of funds per asset that a user can possess.
	// It is set to 2 ^ 256 - 1.
	MaxBalance = abi.MaxUint256
)

Functions

func CalcID

func CalcID(p *channel.Params) (id channel.ID)

CalcID calculates the channelID as needed by the ethereum smart contracts.

func DeployAdjudicator

func DeployAdjudicator(ctx context.Context, backend ContractBackend, deployer accounts.Account) (common.Address, error)

DeployAdjudicator deploys a new Adjudicator contract. Returns txTimedOutError if the context is cancelled or if the context deadline is exceeded when waiting for the transaction to be mined.

func DeployERC20Assetholder

func DeployERC20Assetholder(ctx context.Context, backend ContractBackend, adjudicatorAddr common.Address, tokenAddr common.Address, deployer accounts.Account) (common.Address, error)

DeployERC20Assetholder deploys a new ERC20AssetHolder contract. Returns txTimedOutError if the context is cancelled or if the context deadline is exceeded when waiting for the transaction to be mined.

func DeployETHAssetholder

func DeployETHAssetholder(ctx context.Context, backend ContractBackend, adjudicatorAddr common.Address, deployer accounts.Account) (common.Address, error)

DeployETHAssetholder deploys a new ETHAssetHolder contract. Returns txTimedOutError if the context is cancelled or if the context deadline is exceeded when waiting for the transaction to be mined.

func DeployPerunToken

func DeployPerunToken(ctx context.Context, backend ContractBackend, deployer accounts.Account, initAccs []common.Address, initBals *big.Int) (common.Address, error)

DeployPerunToken deploys a new PerunToken contract. Returns txTimedOutError if the context is cancelled or if the context deadline is exceeded when waiting for the transaction to be mined.

func DeployTrivialApp

func DeployTrivialApp(ctx context.Context, backend ContractBackend, deployer accounts.Account) (common.Address, error)

DeployTrivialApp deploys a new TrivialApp contract. Returns txTimedOutError if the context is cancelled or if the context deadline is exceeded when waiting for the transaction to be mined.

func EncodeParams

func EncodeParams(params *adjudicator.ChannelParams) ([]byte, error)

EncodeParams encodes the parameters as with abi.encode() in the smart contracts.

func EncodeState

func EncodeState(state *adjudicator.ChannelState) ([]byte, error)

EncodeState encodes the state as with abi.encode() in the smart contracts.

func FromEthState

func FromEthState(app channel.App, s *adjudicator.ChannelState) channel.State

FromEthState converts a ChannelState to a channel.State struct.

func FundingID

func FundingID(channelID channel.ID, participant perunwallet.Address) [32]byte

FundingID returns the funding identifier for a participant, i.e., Keccak256(channel id || participant address).

func FundingIDs

func FundingIDs(channelID channel.ID, participants ...perunwallet.Address) [][32]byte

FundingIDs returns a slice the same size as the number of passed participants where each entry contains the hash Keccak256(channel id || participant address).

func HashState

func HashState(s *channel.State) (id channel.ID)

HashState calculates the hash of a state as needed by the ethereum smart contracts.

func IsErrInvalidContractCode

func IsErrInvalidContractCode(err error) bool

IsErrInvalidContractCode returns whether the cause of the error was a invalid bytecode.

func IsErrTxFailed

func IsErrTxFailed(err error) bool

IsErrTxFailed returns whether the cause of the error was a failed transaction.

func Sign

func Sign(acc wallet.Account, s *channel.State) (wallet.Sig, error)

Sign signs the channel state as needed by the ethereum smart contracts.

func ToEthParams

func ToEthParams(p *channel.Params) adjudicator.ChannelParams

ToEthParams converts a channel.Params to a ChannelParams struct.

func ToEthState

func ToEthState(s *channel.State) adjudicator.ChannelState

ToEthState converts a channel.State to a ChannelState struct.

func ValidateAdjudicator

func ValidateAdjudicator(ctx context.Context, backend bind.ContractCaller, adjudicatorAddr common.Address) error

ValidateAdjudicator checks if the bytecode at given address is correct. Returns a ContractBytecodeError if the bytecode at given address is invalid. This error can be checked with function IsErrInvalidContractCode.

func ValidateAssetHolderERC20

func ValidateAssetHolderERC20(ctx context.Context, backend bind.ContractBackend, assetHolderERC20, adjudicator, token common.Address) error

ValidateAssetHolderERC20 checks if the bytecode at the given asset holder ERC20 address is correct and if the adjudicator address is correctly set in the asset holder contract. The contract code at the adjudicator address is not validated, it is the user's responsibility to provide a valid adjudicator address.

Returns a ContractBytecodeError if the bytecode is invalid. This error can be checked with function IsErrInvalidContractCode.

func ValidateAssetHolderETH

func ValidateAssetHolderETH(ctx context.Context, backend bind.ContractBackend, assetHolderETH, adjudicator common.Address) error

ValidateAssetHolderETH checks if the bytecode at the given asset holder ETH address is correct and if the adjudicator address is correctly set in the asset holder contract. The contract code at the adjudicator address is not validated, it is the user's responsibility to provide a valid adjudicator address.

Returns a ContractBytecodeError if the bytecode is invalid. This error can be checked with function IsErrInvalidContractCode.

func Verify

func Verify(addr wallet.Address, s *channel.State, sig wallet.Sig) (bool, error)

Verify verifies that a state was signed correctly.

Types

type Adjudicator

type Adjudicator struct {
	ContractBackend

	// The address to which we send all funds.
	Receiver common.Address
	// contains filtered or unexported fields
}

The Adjudicator struct implements the channel.Adjudicator interface It provides all functionality to close a channel.

func NewAdjudicator

func NewAdjudicator(backend ContractBackend, contract common.Address, receiver common.Address, txSender accounts.Account, gasLimit uint64) *Adjudicator

NewAdjudicator creates a new ethereum adjudicator. The receiver is the on-chain address that receives withdrawals.

func (*Adjudicator) Progress

func (a *Adjudicator) Progress(ctx context.Context, req channel.ProgressReq) error

Progress progresses a channel state on-chain.

func (*Adjudicator) Register

func (a *Adjudicator) Register(ctx context.Context, req channel.AdjudicatorReq, subChannels []channel.SignedState) error

Register registers a state on-chain. If the state is a final state, register becomes a no-op.

func (*Adjudicator) Subscribe

Subscribe returns a new AdjudicatorSubscription to adjudicator events.

func (*Adjudicator) Withdraw

func (a *Adjudicator) Withdraw(ctx context.Context, req channel.AdjudicatorReq, subStates channel.StateMap) error

Withdraw ensures that a channel has been concluded and the final outcome. withdrawn from the asset holders.

type AppID added in v0.5.0

type AppID struct {
	*ethwallet.Address
}

AppID described an app identifier.

func NewRandomAppID added in v0.5.0

func NewRandomAppID(rng *rand.Rand) *AppID

NewRandomAppID calls NewRandomAddress to generate a random Ethereum test address.

func (AppID) Equal added in v0.5.0

func (a AppID) Equal(b channel.AppID) bool

Equal compares two AppID objects for equality.

func (AppID) Key added in v0.5.0

func (a AppID) Key() channel.AppIDKey

Key returns the key representation of this app identifier.

func (AppID) MarshalBinary added in v0.5.0

func (a AppID) MarshalBinary() ([]byte, error)

MarshalBinary marshals the contents of AppID into a byte string.

func (*AppID) UnmarshalBinary added in v0.5.0

func (a *AppID) UnmarshalBinary(data []byte) error

UnmarshalBinary converts a bytestring, representing AppID into the AppID struct.

type AppIDKey added in v0.5.0

type AppIDKey string

AppIDKey is the key representation of an app identifier.

type Asset

type Asset struct {
	ChainID     ChainID
	AssetHolder wallet.Address
}

Asset is an Ethereum asset.

func NewAsset

func NewAsset(chainID *big.Int, assetHolder common.Address) *Asset

NewAsset creates a new asset from an chainID and the AssetHolder address.

func (Asset) Equal

func (a Asset) Equal(b channel.Asset) bool

Equal returns true iff the asset equals the given asset.

func (Asset) EthAddress

func (a Asset) EthAddress() common.Address

EthAddress returns the Ethereum address of the asset.

func (Asset) LedgerID

func (a Asset) LedgerID() multi.LedgerID

LedgerID returns the ledger ID the asset lives on.

func (Asset) MapKey

func (a Asset) MapKey() AssetMapKey

MapKey returns the asset's map key representation.

func (Asset) MarshalBinary

func (a Asset) MarshalBinary() ([]byte, error)

MarshalBinary marshals the asset into its binary representation.

func (*Asset) UnmarshalBinary

func (a *Asset) UnmarshalBinary(data []byte) error

UnmarshalBinary unmarshals the asset from its binary representation.

type AssetMapKey

type AssetMapKey string

AssetMapKey is the map key representation of an asset.

type Backend

type Backend struct{}

Backend implements the interface defined in channel/Backend.go.

func (*Backend) CalcID

func (*Backend) CalcID(p *channel.Params) (id channel.ID)

CalcID calculates the channelID as needed by the ethereum smart contracts.

func (*Backend) NewAppID added in v0.5.0

func (b *Backend) NewAppID() channel.AppID

NewAppID creates a new app identifier, using an empty ethereum struct.

func (*Backend) NewAsset

func (b *Backend) NewAsset() channel.Asset

NewAsset returns a variable of type Asset, which can be used for unmarshalling an asset from its binary representation.

func (*Backend) Sign

func (*Backend) Sign(acc wallet.Account, s *channel.State) (wallet.Sig, error)

Sign signs the channel state as needed by the ethereum smart contracts.

func (*Backend) Verify

func (*Backend) Verify(addr wallet.Address, s *channel.State, sig wallet.Sig) (bool, error)

Verify verifies that a state was signed correctly.

type BlockTimeout

type BlockTimeout struct {
	Time uint64
	// contains filtered or unexported fields
}

BlockTimeout is a timeout on an Ethereum blockchain. A ChainReader is used to wait for the timeout to pass.

This is much better than a channel.TimeTimeout because the local clock might not match the blockchain's timestamp at the point in time when the timeout has passed locally.

func NewBlockTimeout

func NewBlockTimeout(cr ethereum.ChainReader, ts uint64) *BlockTimeout

NewBlockTimeout creates a new BlockTimeout bound to the provided ChainReader and ts as the absolute block.timestamp timeout.

func NewBlockTimeoutDuration

func NewBlockTimeoutDuration(ctx context.Context, cr ethereum.ChainReader, duration uint64) (*BlockTimeout, error)

NewBlockTimeoutDuration creates a new BlockTimeout that elapses duration blockchain seconds added to the current block timestamp in the future.

func (*BlockTimeout) IsElapsed

func (t *BlockTimeout) IsElapsed(ctx context.Context) bool

IsElapsed reads the timestamp from the current blockchain header to check whether the timeout has passed yet.

func (*BlockTimeout) String

func (t *BlockTimeout) String() string

String returns a string stating the block timeout as a unix timestamp.

func (*BlockTimeout) Wait

func (t *BlockTimeout) Wait(ctx context.Context) error

Wait subscribes to new blocks until the timeout is reached. It returns the context error if it is canceled before the timeout is reached.

type ChainID

type ChainID struct {
	*big.Int
}

ChainID identifies a specific Ethereum backend.

func MakeChainID

func MakeChainID(id *big.Int) ChainID

MakeChainID makes a ChainID for the given id.

func (ChainID) MapKey

func (id ChainID) MapKey() multi.LedgerIDMapKey

MapKey returns the asset's map key representation.

func (ChainID) MarshalBinary

func (id ChainID) MarshalBinary() (data []byte, err error)

MarshalBinary marshals the chainID into its binary representation.

func (*ChainID) UnmarshalBinary

func (id *ChainID) UnmarshalBinary(data []byte) error

UnmarshalBinary unmarshals the chainID from its binary representation.

type ContractBackend

type ContractBackend struct {
	ContractInterface
	// contains filtered or unexported fields
}

ContractBackend adds a keystore and an on-chain account to the ContractInterface. This is needed to send on-chain transaction to interact with the smart contracts.

func NewContractBackend

func NewContractBackend(cf ContractInterface, chainID ChainID, tr Transactor, txFinalityDepth uint64) ContractBackend

NewContractBackend creates a new ContractBackend with the given parameters. txFinalityDepth defines in how many consecutive blocks a TX has to be included to be considered final. Must be at least 1.

func (*ContractBackend) ChainID

func (c *ContractBackend) ChainID() ChainID

ChainID returns the chain identifier of the contract backend.

func (*ContractBackend) ConfirmTransaction

func (c *ContractBackend) ConfirmTransaction(ctx context.Context, tx *types.Transaction, acc accounts.Account) (*types.Receipt, error)

ConfirmTransaction returns the receipt of the transaction if it was included in at least `TxFinalityDepth` many blocks at one point in time. Returns `txTimedOutError` on context timeout or cancel.

func (*ContractBackend) NewFilterOpts

func (c *ContractBackend) NewFilterOpts(ctx context.Context) (*bind.FilterOpts, error)

NewFilterOpts returns bind.FilterOpts with the field Start set to the block number 100 blocks ago (or 1) and the field End set to nil and the ctx field set to the passed context.

func (*ContractBackend) NewTransactor

func (c *ContractBackend) NewTransactor(ctx context.Context, gasLimit uint64, acc accounts.Account) (*bind.TransactOpts, error)

NewTransactor returns bind.TransactOpts with the context, gas limit and account set as specified, using the ContractBackend's Transactor.

The gas price and nonce are not set and will be set by go-ethereum automatically when not manually specified by the caller. The caller must also set the value manually afterwards if it should be different from 0.

func (*ContractBackend) NewWatchOpts

func (c *ContractBackend) NewWatchOpts(ctx context.Context) (*bind.WatchOpts, error)

NewWatchOpts returns bind.WatchOpts with the field Start set to the current block number and the ctx field set to the passed context.

func (*ContractBackend) TxFinalityDepth

func (c *ContractBackend) TxFinalityDepth() uint64

TxFinalityDepth returns the transaction finality depth of the contract backend.

type ContractInterface

type ContractInterface interface {
	bind.ContractBackend
	ethereum.ChainReader
	ethereum.TransactionReader
}

ContractInterface provides all functions needed by an ethereum backend. Both test.SimulatedBackend and ethclient.Client implement this interface.

type DepositReq

type DepositReq struct {
	Balance   channel.Bal      // How much should be deposited.
	CB        ContractBackend  // Used to bind contracts and send TX.
	Account   accounts.Account // Depositor's account.
	Asset     Asset            // Address of the AssetHolder.
	FundingID [32]byte         // Needed by the AssetHolder.
}

DepositReq contains all necessary data for a `Depositor` to deposit funds. It is much smaller than a `FundingReq` and only holds the information for one Funding-ID.

func NewDepositReq

func NewDepositReq(balance channel.Bal, cb ContractBackend, asset Asset, account accounts.Account, fundingID [32]byte) *DepositReq

NewDepositReq returns a new `DepositReq`.

type DepositResult added in v0.5.0

type DepositResult struct {
	Transactions types.Transactions
	Error        error
}

DepositResult is created to keep track of the returned values.

type Depositor

type Depositor interface {
	// Deposit returns the transactions needed for the deposit or an error.
	// The transactions should already be sent to the chain, such that
	// `abi/bind.WaitMined` can be used to await their success.
	// When one of the TX fails, the status of the following ones is ignored.
	Deposit(context.Context, DepositReq) (types.Transactions, error)

	// NumTX returns how many transactions a `Deposit` call needs.
	NumTX() uint32
}

Depositor is used by the `Funder` to deposit funds for ledger channel funding. Depositor are reusable such that one Depositor per asset is enough.

type ERC20Depositor

type ERC20Depositor struct {
	Token    common.Address
	GasLimit uint64
}

ERC20Depositor deposits tokens into the `AssetHolderERC20` contract. It is bound to a token but can be reused to deposit multiple times.

func NewERC20Depositor

func NewERC20Depositor(token common.Address, gasLimit uint64) *ERC20Depositor

NewERC20Depositor creates a new ERC20Depositor.

func (*ERC20Depositor) Approve added in v0.5.0

func (d *ERC20Depositor) Approve(ctx context.Context, lock *sync.Mutex, req DepositReq, callOpts bind.CallOpts) (*types.Transaction, bool, error)

Approve locks the lock argument and Approves the requested balance + the current allowance of the requested account.

func (*ERC20Depositor) Deposit

Deposit approves the value to be swapped and calls DepositOnly.

func (*ERC20Depositor) DepositOnly added in v0.5.0

func (d *ERC20Depositor) DepositOnly(ctx context.Context, req DepositReq) (*types.Transaction, error)

DepositOnly deposits ERC20 tokens into the ERC20 AssetHolder specified at the requests asset address.

func (*ERC20Depositor) NumTX

func (*ERC20Depositor) NumTX() uint32

NumTX returns 2 since it does IncreaseAllowance and Deposit.

type ETHDepositor

type ETHDepositor struct {
	GasLimit uint64
}

ETHDepositor deposits funds into the `AssetHolderETH` contract. It has no state and is therefore completely reusable.

func NewETHDepositor

func NewETHDepositor(gasLimit uint64) *ETHDepositor

NewETHDepositor creates a new ETHDepositor.

func (*ETHDepositor) Deposit

func (d *ETHDepositor) Deposit(ctx context.Context, req DepositReq) (types.Transactions, error)

Deposit deposits ether into the ETH AssetHolder specified at the requests's asset address.

func (*ETHDepositor) NumTX

func (*ETHDepositor) NumTX() uint32

NumTX returns 1 since it only does Deposit.

type Funder

type Funder struct {
	ContractBackend
	// contains filtered or unexported fields
}

Funder implements the channel.Funder interface for Ethereum.

In addition to the `Fund` method required by the `Funder` interface, it also provides additional functions for convenience.

All the exported methods are thread-safe and can be invoked concurrently.

func NewFunder

func NewFunder(backend ContractBackend) *Funder

NewFunder creates a new ethereum funder.

func (*Funder) Fund

func (f *Funder) Fund(ctx context.Context, request channel.FundingReq) error

Fund implements the channel.Funder interface. It funds all assets in parallel. If not all participants successfully fund within a timeframe of ChallengeDuration seconds, Fund returns a FundingTimeoutError.

If funding on a real blockchain, make sure that the passed context doesn't cancel before the funding period of length ChallengeDuration elapses, or funding will be canceled prematurely.

func (*Funder) IsAssetRegistered

func (f *Funder) IsAssetRegistered(asset Asset) (Depositor, accounts.Account, bool)

IsAssetRegistered returns if the specified asset is registered in the funder or not. If is registered, then the corresponding depositor and account will also be returned.

func (*Funder) NumTX

func (f *Funder) NumTX(req channel.FundingReq) (sum uint32, err error)

NumTX returns how many Transactions are needed for the funding request.

func (*Funder) RegisterAsset

func (f *Funder) RegisterAsset(asset Asset, d Depositor, acc accounts.Account) bool

RegisterAsset registers the depositor and account for the specified asset in the funder.

Deposits for this asset will be sent using the depositors from the specified account when funding. Hence, it is the responsibility of the caller to ensure, the account has sufficient balance in the asset.

It returns true if the asset was successfully registered, false if it was already present.

type NoOpDepositor

type NoOpDepositor struct{}

NoOpDepositor is a depositor that does nothing. For example, it can be used for the multi-ledger funder for assets that registered on a different ledger.

func NewNoOpDepositor

func NewNoOpDepositor() *NoOpDepositor

NewNoOpDepositor creates a new NoOpDepositor.

func (*NoOpDepositor) Deposit

Deposit does nothing.

func (*NoOpDepositor) NumTX

func (*NoOpDepositor) NumTX() uint32

NumTX returns 0 since the depositor does nothing.

type OnChainTxType

type OnChainTxType int

OnChainTxType defines the type of on-chain transaction function names that can be returned in TxTimeoutError.

const (
	Fund OnChainTxType = iota
	Register
	Progress
	Conclude
	ConcludeFinal
	Withdraw
)

Enumeration of valid transaction types.

Fund funds the channel for a given user. Register registers a state of the channel. The state be concluded after the challenge duration has passed. Progress progresses the state of the channel directly on the blockchain. Conclude concludes the state of a channel after it had been registered and the challenge duration has passed. ConcludeFinal directly concludes the finalized state of the channel without registering it. Withdraw withdraws the funds for a given user after the channel was concluded.

func (OnChainTxType) String

func (t OnChainTxType) String() string

type RegisteredSub

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

RegisteredSub implements the channel.AdjudicatorSubscription interface.

func (*RegisteredSub) Close

func (r *RegisteredSub) Close() error

Close closes this subscription. Any pending calls to Next will return nil.

func (*RegisteredSub) Err

func (r *RegisteredSub) Err() error

Err returns the error of the event subscription. Should only be called after Next returned nil.

func (*RegisteredSub) Next

Next returns the newest past or next blockchain event. It blocks until an event is returned from the blockchain or the subscription is closed. If the subscription is closed, Next immediately returns nil. If there was a past event when the subscription was set up, the first call to Next will return it.

type Transactor

type Transactor interface {
	NewTransactor(account accounts.Account) (*bind.TransactOpts, error)
}

Transactor can be used to make transactOpts for a given account.

Directories

Path Synopsis
Package errors contains error checking and wrapping functions.
Package errors contains error checking and wrapping functions.
Package test contains utilities for testing the Ethereum channel backend, such as a simulated blockchain backend and a custom Adjudicator.
Package test contains utilities for testing the Ethereum channel backend, such as a simulated blockchain backend and a custom Adjudicator.

Jump to

Keyboard shortcuts

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