escrow

package
v0.1.10-64-g7180dea Latest Latest
Warning

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

Go to latest
Published: May 27, 2019 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// PaymentChannelIDHeader is a MultiPartyEscrow contract payment channel
	// id. Value is a string containing a decimal number.
	PaymentChannelIDHeader = "snet-payment-channel-id"
	// PaymentChannelNonceHeader is a payment channel nonce value. Value is a
	// string containing a decimal number.
	PaymentChannelNonceHeader = "snet-payment-channel-nonce"
	// PaymentChannelAmountHeader is an amount of payment channel value
	// which server is authorized to withdraw after handling the RPC call.
	// Value is a string containing a decimal number.
	PaymentChannelAmountHeader = "snet-payment-channel-amount"
	// PaymentChannelSignatureHeader is a signature of the client to confirm
	// amount withdrawing authorization. Value is an array of bytes.
	PaymentChannelSignatureHeader = "snet-payment-channel-signature-bin"

	// EscrowPaymentType each call should have id and nonce of payment channel
	// in metadata.
	EscrowPaymentType = "escrow"
)

Variables

This section is empty.

Functions

func NewMemStorage

func NewMemStorage() (storage *memoryStorage)

NewMemStorage returns new in-memory atomic storage implementation

func NewPaymentHandler

func NewPaymentHandler(
	service PaymentChannelService,
	processor *blockchain.Processor,
	incomeValidator IncomeValidator) handler.PaymentHandler

NewPaymentHandler retuns new MultiPartyEscrow contract payment handler.

Types

type AtomicStorage

type AtomicStorage interface {
	// Get returns value by key. ok value indicates whether passed key is
	// present in the storage. err indicates storage error.
	Get(key string) (value string, ok bool, err error)
	// GetByKeyPrefix returns list of values which keys has given prefix.
	GetByKeyPrefix(prefix string) (values []string, err error)
	// Put uncoditionally writes value by key in storage, err is not nil in
	// case of storage error.
	Put(key string, value string) (err error)
	// PutIfAbsent writes value if and only if key is absent in storage. ok is
	// true if key was absent and false otherwise. err indicates storage error.
	PutIfAbsent(key string, value string) (ok bool, err error)
	// CompareAndSwap atomically replaces prevValue by newValue. If ok flag is
	// true and err is nil then operation was successful. If err is nil and ok
	// is false then operation failed because prevValue is not equal to current
	// value. err indicates storage error.
	CompareAndSwap(key string, prevValue string, newValue string) (ok bool, err error)
	// Delete removes value by key
	Delete(key string) (err error)
}

AtomicStorage is an interface to key-value storage with atomic operations.

type BlockchainChannelReader

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

BlockchainChannelReader reads channel state from blockchain

func NewBlockchainChannelReader

func NewBlockchainChannelReader(processor *blockchain.Processor, cfg *viper.Viper, metadata *blockchain.ServiceMetadata) *BlockchainChannelReader

NewBlockchainChannelReader returns new instance of blockchain channel reader

func (*BlockchainChannelReader) GetChannelStateFromBlockchain

func (reader *BlockchainChannelReader) GetChannelStateFromBlockchain(key *PaymentChannelKey) (channel *PaymentChannelData, ok bool, err error)

GetChannelStateFromBlockchain returns channel state from Ethereum blockchain. ok is false if channel was not found.

type ChannelPaymentValidator

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

ChannelPaymentValidator validates payment using payment channel state.

func NewChannelPaymentValidator

func NewChannelPaymentValidator(processor *blockchain.Processor, cfg *viper.Viper, metadata *blockchain.ServiceMetadata) *ChannelPaymentValidator

NewChannelPaymentValidator returns new payment validator instance

func (*ChannelPaymentValidator) Validate

func (validator *ChannelPaymentValidator) Validate(payment *Payment, channel *PaymentChannelData) (err error)

Validate returns instance of PaymentError as error if validation fails, nil otherwise.

type ChannelUpdate

type ChannelUpdate func(channel *PaymentChannelData)

ChannelUpdate is an type of channel update which should be applied when StartClaim() method is called.

var (
	// CloseChannel is an update which zeroes full amount of the channel to
	// designate that channel sender should add funds to the channel before
	// continue working.
	CloseChannel ChannelUpdate = func(channel *PaymentChannelData) {
		channel.FullAmount = big.NewInt(0)
	}
	// IncrementChannelNonce is an update which increments channel nonce and
	// descreases full amount to allow channel sender continue working with
	// remaining amount.
	IncrementChannelNonce ChannelUpdate = func(channel *PaymentChannelData) {
		channel.Nonce = (&big.Int{}).Add(channel.Nonce, big.NewInt(1))
		channel.FullAmount = (&big.Int{}).Sub(channel.FullAmount, channel.AuthorizedAmount)
		channel.AuthorizedAmount = big.NewInt(0)
		channel.Signature = nil
	}
)

type Claim

type Claim interface {
	// Payment returns the payment which is being claimed, caller uses details of
	// the payment to start blockchain transaction.
	Payment() *Payment
	// Finish to be called after blockchain transaction is finished successfully.
	// Updates repository state.
	Finish() error
}

Claim is a handle of payment channel claim in progress. It is returned by StartClaim method and provides caller information about payment to call MultiPartyEscrow.channelClaim function. After transaction is written to blockchain caller should call Finish() method to update payment repository state.

type IncomeData

type IncomeData struct {
	// Income is a difference between previous authorized amount and amount
	// which was received with current call.
	Income *big.Int
	// GrpcContext contains gRPC stream context information. For instance
	// metadata could be used to pass invoice id to check pricing.
	GrpcContext *handler.GrpcStreamContext
}

IncomeData is used to pass information to the pricing validation system. This system can use information about call to calculate price and verify income received.

type IncomeValidator

type IncomeValidator interface {
	// Validate returns nil if validation is successful or correct PaymentError
	// status to be sent to client in case of validation error.
	Validate(*IncomeData) (err error)
}

IncomeValidator uses pricing information to check that call was payed correctly by channel sender. This interface can be implemented differently depending on pricing policy. For instance one can verify that call is payed according to invoice. Each RPC method can have different price and so on. To implement this strategies additional information from gRPC context can be required. In such case it should be added into handler.GrpcStreamContext.

func NewIncomeValidator

func NewIncomeValidator(priceInCogs *big.Int) (validator IncomeValidator)

NewIncomeValidator returns new income validator instance

type Lock

type Lock interface {
	// Unlock frees lock
	Unlock() (err error)
}

Lock is an aquired lock.

type Locker

type Locker interface {
	// Lock aquires and returns lock. ok is false if lock cannot be aquired.
	Lock(name string) (lock Lock, ok bool, err error)
}

Locker is an interface to aquire lock

func NewEtcdLocker

func NewEtcdLocker(storage AtomicStorage) Locker

NewEtcdLocker returns new lock which is based on etcd storage.

type Payment

type Payment struct {
	// MpeContractAddress is an address of the MultiPartyEscrow contract which
	// were used to open the payment channel.
	MpeContractAddress common.Address
	// ChannelID is an id of the payment channel used.
	ChannelID *big.Int
	// ChannelNonce is a nonce of the payment channel.
	ChannelNonce *big.Int
	// Amount is an amount of the payment.
	Amount *big.Int
	// Signature is a signature of the payment.
	Signature []byte
}

Payment contains MultiPartyEscrow payment details

func (*Payment) ID

func (p *Payment) ID() string

func (*Payment) String

func (p *Payment) String() string

type PaymentChannelData

type PaymentChannelData struct {
	// ChannelID is an id of the channel
	ChannelID *big.Int
	// Nonce is a nonce of this channel state
	Nonce *big.Int
	// State is a payment channel state: Open or Closed.
	State PaymentChannelState
	// Sender is an Ethereum address of the client which created the channel.
	// It is and address to be charged for RPC call.
	Sender common.Address
	// Recipient is an address which can claim funds from channel using
	// signature. It is an address of service provider.
	Recipient common.Address
	// GroupID is an id of the group of service replicas which share the same
	// payment channel.
	GroupID [32]byte
	// FullAmount is an amount which is deposited in channel by Sender.
	FullAmount *big.Int
	// Expiration is a time at which channel will be expired. This time is
	// expressed in Ethereum block number. Since this block is added to
	// blockchain Sender can withdraw tokens from channel.
	Expiration *big.Int
	// Signer is and address to be used to sign the payments. Usually it is
	// equal to channel sender.
	Signer common.Address

	// service provider. This amount increments on price after each successful
	// RPC call.
	AuthorizedAmount *big.Int
	// Signature is a signature of last message containing Authorized amount.
	// It is required to claim tokens from channel.
	Signature []byte
}

PaymentChannelData is to keep all channel related information.

func MergeStorageAndBlockchainChannelState

func MergeStorageAndBlockchainChannelState(storage, blockchain *PaymentChannelData) (merged *PaymentChannelData)

MergeStorageAndBlockchainChannelState merges two instances of payment channel: one read from storage, one from blockchain.

func (*PaymentChannelData) String

func (data *PaymentChannelData) String() string

type PaymentChannelKey

type PaymentChannelKey struct {
	ID *big.Int
}

PaymentChannelKey specifies the channel in MultiPartyEscrow contract. It consists of two parts: channel id and channel nonce. Channel nonce is incremented each time when amount of tokens in channel descreases. Nonce allows reusing channel id without risk of overexpenditure.

func (*PaymentChannelKey) String

func (key *PaymentChannelKey) String() string

type PaymentChannelService

type PaymentChannelService interface {
	// PaymentChannel returns latest payment channel state. This method uses
	// shared storage and blockchain to construct and return latest channel
	// state.
	PaymentChannel(key *PaymentChannelKey) (channel *PaymentChannelData, ok bool, err error)
	// ListChannels returns list of payment channels from payment channel
	// storage.
	ListChannels() (channels []*PaymentChannelData, err error)

	// StartClaim gets channel from storage, applies update on it and adds
	// payment for claiming into the storage.
	StartClaim(key *PaymentChannelKey, update ChannelUpdate) (claim Claim, err error)
	// ListClaims returns list of payment claims in progress
	ListClaims() (claim []Claim, err error)

	// StartPaymentTransaction validates payment and starts payment transaction
	StartPaymentTransaction(payment *Payment) (transaction PaymentTransaction, err error)

	//Get Channel from BlockChain
	PaymentChannelFromBlockChain(key *PaymentChannelKey) (channel *PaymentChannelData, ok bool, err error)
}

PaymentChannelService interface is API for payment channel functionality.

func NewPaymentChannelService

func NewPaymentChannelService(
	storage *PaymentChannelStorage,
	paymentStorage *PaymentStorage,
	blockchainReader *BlockchainChannelReader,
	locker Locker,
	channelPaymentValidator *ChannelPaymentValidator, groupIdReader func() ([32]byte, error)) PaymentChannelService

NewPaymentChannelService returns instance of PaymentChannelService to work with payments via MultiPartyEscrow contract.

type PaymentChannelState

type PaymentChannelState int

PaymentChannelState is a current state of a payment channel. Payment channel may be in Open or Closed state.

const (
	// Open means that channel is open and can be used to pay for calls.
	Open PaymentChannelState = 0
	// Closed means that channel is closed cannot be used to pay for calls.
	Closed PaymentChannelState = 1
)

func (PaymentChannelState) String

func (state PaymentChannelState) String() string

type PaymentChannelStateService

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

PaymentChannelStateService is an implementation of PaymentChannelStateServiceServer gRPC interface

func NewPaymentChannelStateService

func NewPaymentChannelStateService(channelService PaymentChannelService) *PaymentChannelStateService

NewPaymentChannelStateService returns new instance of PaymentChannelStateService

func (*PaymentChannelStateService) GetChannelState

func (service *PaymentChannelStateService) GetChannelState(context context.Context, request *ChannelStateRequest) (reply *ChannelStateReply, err error)

GetChannelState returns the latest state of the channel which id is passed in request. To authenticate sender request should also contain correct signature of the channel id.

type PaymentChannelStorage

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

PaymentChannelStorage is a storage for PaymentChannelData by PaymentChannelKey based on TypedAtomicStorage implementation

func NewPaymentChannelStorage

func NewPaymentChannelStorage(atomicStorage AtomicStorage) *PaymentChannelStorage

NewPaymentChannelStorage returns new instance of PaymentChannelStorage implementation

func (*PaymentChannelStorage) CompareAndSwap

func (storage *PaymentChannelStorage) CompareAndSwap(key *PaymentChannelKey, prevState *PaymentChannelData, newState *PaymentChannelData) (ok bool, err error)

CompareAndSwap compares previous storage value and set new value by key

func (*PaymentChannelStorage) Get

func (storage *PaymentChannelStorage) Get(key *PaymentChannelKey) (state *PaymentChannelData, ok bool, err error)

Get returns payment channel by key

func (*PaymentChannelStorage) GetAll

func (storage *PaymentChannelStorage) GetAll() (states []*PaymentChannelData, err error)

GetAll returns all channels from the storage

func (*PaymentChannelStorage) Put

func (storage *PaymentChannelStorage) Put(key *PaymentChannelKey, state *PaymentChannelData) (err error)

Put stores payment channel by key

func (*PaymentChannelStorage) PutIfAbsent

func (storage *PaymentChannelStorage) PutIfAbsent(key *PaymentChannelKey, state *PaymentChannelData) (ok bool, err error)

PutIfAbsent storage payment channel by key if key is absent

type PaymentError

type PaymentError struct {
	// Code is error code
	Code PaymentErrorCode
	// Message is message
	Message string
}

PaymentError contains error code and message and implements Error interface.

func NewPaymentError

func NewPaymentError(code PaymentErrorCode, format string, msg ...interface{}) *PaymentError

NewPaymentError constructs new PaymentError instance with given error code and message.

func (*PaymentError) Error

func (err *PaymentError) Error() string

type PaymentErrorCode

type PaymentErrorCode int

PaymentErrorCode contains all types of errors which we need to handle on the client side.

const (
	// Internal error code means that error is caused by improper daemon
	// configuration or functioning. Client cannot do anything with it.
	Internal PaymentErrorCode = 1
	// Unauthenticated error code means that client sent payment which cannot
	// be applied to the channel.
	Unauthenticated PaymentErrorCode = 2
	// FailedPrecondition means that request cannot be handled because system
	// is not in appropriate state.
	FailedPrecondition PaymentErrorCode = 3
	// IncorrectNonce is returned when nonce value sent by client is incorrect.
	IncorrectNonce PaymentErrorCode = 4
)

type PaymentStorage

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

PaymentStorage is a storage for PaymentChannelData by PaymentChannelKey based on TypedAtomicStorage implementation

func NewPaymentStorage

func NewPaymentStorage(atomicStorage AtomicStorage) *PaymentStorage

NewPaymentStorage returns new instance of PaymentStorage implementation

func (*PaymentStorage) Delete

func (storage *PaymentStorage) Delete(payment *Payment) (err error)

func (*PaymentStorage) GetAll

func (storage *PaymentStorage) GetAll() (states []*Payment, err error)

func (*PaymentStorage) Put

func (storage *PaymentStorage) Put(payment *Payment) (err error)

type PaymentTransaction

type PaymentTransaction interface {
	// Channel returns the channel which is used to apply the payment
	Channel() *PaymentChannelData
	// Commit finishes transaction and applies payment.
	Commit() error
	// Rollback rolls transaction back.
	Rollback() error
}

PaymentTransaction is a payment transaction in progress.

type PrefixedAtomicStorage

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

PrefixedAtomicStorage is decorator for atomic storage which adds a prefix to the storage keys.

func NewLockerStorage

func NewLockerStorage(storage AtomicStorage) *PrefixedAtomicStorage

returns new prefixed storage

func (*PrefixedAtomicStorage) CompareAndSwap

func (storage *PrefixedAtomicStorage) CompareAndSwap(key string, prevValue string, newValue string) (ok bool, err error)

CompareAndSwap is implementation of AtomicStorage.CompareAndSwap

func (*PrefixedAtomicStorage) Delete

func (storage *PrefixedAtomicStorage) Delete(key string) (err error)

func (*PrefixedAtomicStorage) Get

func (storage *PrefixedAtomicStorage) Get(key string) (value string, ok bool, err error)

Get is implementation of AtomicStorage.Get

func (*PrefixedAtomicStorage) GetByKeyPrefix

func (storage *PrefixedAtomicStorage) GetByKeyPrefix(prefix string) (values []string, err error)

func (*PrefixedAtomicStorage) Put

func (storage *PrefixedAtomicStorage) Put(key string, value string) (err error)

Put is implementation of AtomicStorage.Put

func (*PrefixedAtomicStorage) PutIfAbsent

func (storage *PrefixedAtomicStorage) PutIfAbsent(key string, value string) (ok bool, err error)

PutIfAbsent is implementation of AtomicStorage.PutIfAbsent

type ProviderControlService

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

func NewProviderControlService

func NewProviderControlService(channelService PaymentChannelService, metaData *blockchain.ServiceMetadata) *ProviderControlService

func (*ProviderControlService) GetListInProgress

func (service *ProviderControlService) GetListInProgress(ctx context.Context, request *GetPaymentsListRequest) (reply *PaymentsListReply, err error)

Get the list of all claims that have been initiated but not completed yet. Verify that mpe_address is correct Verify that actual block_number is not very different (+-5 blocks) from the current_block_number from the signature Verify that message was signed by the service provider (“payment_address” in metadata should match to the signer). Check for any claims already done on block chain but have not been reflected in the storage yet, update the storage status by calling the Finish() method on such claims.

func (*ProviderControlService) GetListUnclaimed

func (service *ProviderControlService) GetListUnclaimed(ctx context.Context, request *GetPaymentsListRequest) (paymentReply *PaymentsListReply, err error)

Get list of unclaimed payments, we do this by getting the list of channels in progress which have some amount to be claimed. Verify that mpe_address is correct Verify that actual block_number is not very different (+-5 blocks) from the current_block_number from the signature Verify that message was signed by the service provider (“payment_address” in metadata should match to the signer). Send list of unclaimed payments

func (*ProviderControlService) StartClaim

func (service *ProviderControlService) StartClaim(ctx context.Context, startClaim *StartClaimRequest) (paymentReply *PaymentReply, err error)

Initialize the claim for specific channel Verify that the “payment_address” in meta data matches to that of the signer. Increase nonce and send last payment with old nonce to the caller. Begin the claim process on the current channel and Increment the channel nonce and decrease the full amount to allow channel sender to continue working with remaining amount. Check for any claims already done on block chain but have not been reflected in the storage yet, update the storage status by calling the Finish() method on such claims

type TypedAtomicStorage

type TypedAtomicStorage interface {
	// Get returns value by key
	Get(key interface{}) (value interface{}, ok bool, err error)
	// GetAll returns an array which contains all values from storage
	GetAll() (array interface{}, err error)
	// Put puts value by key unconditionally
	Put(key interface{}, value interface{}) (err error)
	// PutIfAbsent puts value by key if and only if key is absent in storage
	PutIfAbsent(key interface{}, value interface{}) (ok bool, err error)
	// CompareAndSwap puts newValue by key if and only if previous value is equal
	// to prevValue
	CompareAndSwap(key interface{}, prevValue interface{}, newValue interface{}) (ok bool, err error)
	// Delete removes value by key
	Delete(key interface{}) (err error)
}

TypedAtomicStorage is an atomic storage which automatically serializes/deserializes values and keys

type TypedAtomicStorageImpl

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

TypedAtomicStorageImpl is an implementation of TypedAtomicStorage interface

func (*TypedAtomicStorageImpl) CompareAndSwap

func (storage *TypedAtomicStorageImpl) CompareAndSwap(key interface{}, prevValue interface{}, newValue interface{}) (ok bool, err error)

CompareAndSwap implements TypedAtomicStorage.CompareAndSwap

func (*TypedAtomicStorageImpl) Delete

func (storage *TypedAtomicStorageImpl) Delete(key interface{}) (err error)

func (*TypedAtomicStorageImpl) Get

func (storage *TypedAtomicStorageImpl) Get(key interface{}) (value interface{}, ok bool, err error)

Get implements TypedAtomicStorage.Get

func (*TypedAtomicStorageImpl) GetAll

func (storage *TypedAtomicStorageImpl) GetAll() (array interface{}, err error)

func (*TypedAtomicStorageImpl) Put

func (storage *TypedAtomicStorageImpl) Put(key interface{}, value interface{}) (err error)

Put implementor TypedAtomicStorage.Put

func (*TypedAtomicStorageImpl) PutIfAbsent

func (storage *TypedAtomicStorageImpl) PutIfAbsent(key interface{}, value interface{}) (ok bool, err error)

PutIfAbsent implements TypedAtomicStorage.PutIfAbsent

Jump to

Keyboard shortcuts

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