escrow

package
v4.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2020 License: MIT Imports: 22 Imported by: 3

README

Signatures used for Authorization in Daemon



Type of Request Check for State or Execute Service Block chain Mode allowed User Flag Request Signature expected Method Called Response sent Comments
Paid Call Grpc State call true NA message ChannelStateRequest "__get_channel_state"+MpeAddress+channelID+CurrentBlockNumber
Bytes Constructed
rpc GetChannelState(ChannelStateRequest) returns (ChannelStateReply) {} message ChannelStateReply Only channel signer/sender/receiver can get latest channel state . Current Block Number passed needs to be +-10 from the latest block number retrieved from the blockchain
Paid Call Grpc State call false NA message ChannelStateRequest NA rpc GetChannelState(ChannelStateRequest) returns (ChannelStateReply) {} message ChannelStateReply Same response is sent every time,Caller would not know if the block chain mode is enabled or disabled.The Signature sent is ignored.
Paid Call Execute Service true true or false Metadata Passed to Daemon should consist of the below header
"snet-payment-type"="escrow"
"snet-payment-channel-id" = "Channeld"
"snet-payment-channel-nonce"="Nonce"
"snet-payment-channel-amount" ="TotalAmount"
"snet-payment-channel-signature-bin"="Signature"
"__MPE_claim_message"+MpeContractAddress+ChannelID+ChannelNonce+SignedAmount
Bytes Constructed
Call to the method in Service Response sent by Service Only channel signer/sender can sign.
, Please note the Total Amount = Amount (retrieved from State call) + Price of the current call , latest nonce is also retrieved from the state call
if the allowed_user flag is true , then Make sure the Signer is also in the list of allowed users defined in the Daemon config.
Please note the allowed user flag is applicable only in test networks like ropsten / kovan etc; but not in mainnet


Details on headers

Documentation

Index

Constants

View Source
const (
	USED_AMOUNT    string = "U"
	PLANNED_AMOUNT string = "P"
	REFUND_AMOUNT  string = "R"
)
View Source
const (
	PrefixInSignature = "__MPE_claim_message"
	//Agreed constant value
	FreeCallPrefixSignature = "__prefix_free_trial"
	//Agreed constant value
	AllowedUserPrefixSignature = "__authorized_user"
)
View Source
const (

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

	// EscrowPaymentType each call should have id and nonce of payment channel
	// in metadata.
	FreeCallPaymentType = "free-call"
)
View Source
const (
	PrePaidPaymentType = "prepaid-call"
)

Variables

This section is empty.

Functions

func AllowedUserPaymentHandler

func AllowedUserPaymentHandler() handler.PaymentHandler

func FreeCallPaymentHandler added in v1.1.1

func FreeCallPaymentHandler(
	freeCallService FreeCallUserService, processor *blockchain.Processor, metadata *blockchain.OrganizationMetaData,
	pServiceMetaData *blockchain.ServiceMetadata) handler.PaymentHandler

NewPaymentHandler returns new MultiPartyEscrow contract payment handler.

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.

func NewPrePaidPaymentHandler

func NewPrePaidPaymentHandler(
	PrePaidService PrePaidService, metadata *blockchain.OrganizationMetaData,
	pServiceMetaData *blockchain.ServiceMetadata, pricing *pricing.PricingStrategy, manager token.Manager) handler.PaymentHandler

NewPaymentHandler returns new MultiPartyEscrow contract payment handler.

func PaymentID added in v1.0.0

func PaymentID(channelID *big.Int, channelNonce *big.Int) string

func PublishChannelStats

func PublishChannelStats(payment handler.Payment) (err *handler.GrpcError)

Types

type AllowedUserPaymentValidator

type AllowedUserPaymentValidator struct {
}

func (*AllowedUserPaymentValidator) Validate

func (validator *AllowedUserPaymentValidator) Validate(payment *Payment) (err error)

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)

	StartTransaction(conditionKeys []string) (transaction Transaction, err error)
	CompleteTransaction(transaction Transaction, update []KeyValueData) (ok bool, err error)
	ExecuteTransaction(request CASRequest) (ok bool, err error)
}

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

type BlockChainDisabledFreeCallStateService

type BlockChainDisabledFreeCallStateService struct {
}

func (*BlockChainDisabledFreeCallStateService) GetFreeCallsAvailable

func (service *BlockChainDisabledFreeCallStateService) GetFreeCallsAvailable(context.Context, *FreeCallStateRequest) (*FreeCallStateReply, error)

type BlockChainDisabledProviderControlService added in v1.1.1

type BlockChainDisabledProviderControlService struct {
}

func (*BlockChainDisabledProviderControlService) GetListInProgress added in v1.1.1

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

func (*BlockChainDisabledProviderControlService) GetListUnclaimed added in v1.1.1

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

func (*BlockChainDisabledProviderControlService) StartClaim added in v1.1.1

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

func (*BlockChainDisabledProviderControlService) StartClaimForMultipleChannels

func (service *BlockChainDisabledProviderControlService) StartClaimForMultipleChannels(ctx context.Context, request *StartMultipleClaimRequest) (reply *PaymentsListReply, err error)

type BlockChainDisabledStateService added in v1.1.1

type BlockChainDisabledStateService struct {
}

func (*BlockChainDisabledStateService) GetChannelState added in v1.1.1

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

type BlockChainDisabledTokenService

type BlockChainDisabledTokenService struct {
}

func (BlockChainDisabledTokenService) GetToken

func (service BlockChainDisabledTokenService) GetToken(ctx context.Context, request *TokenRequest) (reply *TokenReply, err error)

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,
	orgMetadata *blockchain.OrganizationMetaData) *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 CASRequest

type CASRequest struct {
	RetryTillSuccessOrError bool
	Update                  UpdateFunc
	ConditionKeys           []string
}

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.OrganizationMetaData) *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
	// decreases 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 ConditionFunc

type ConditionFunc func(conditionValues []TypedKeyValueData, revisedAmount *big.Int, channelId *big.Int) ([]TypedKeyValueData, error)

Defines the condition that needs to be met, it generates the respective typed Data when conditions are satisfied, you define your own validations in here It takes in the latest typed values read.

var (
	IncrementUsedAmount ConditionFunc = func(conditionValues []TypedKeyValueData, revisedAmount *big.Int, channelId *big.Int) (newValues []TypedKeyValueData, err error) {
		oldState, err := convertTypedDataToPrePaidUsage(conditionValues)
		if err != nil {
			return nil, err
		}
		oldState.ChannelID = channelId
		newState := oldState.Clone()
		usageKey := PrePaidDataKey{UsageType: USED_AMOUNT, ChannelID: oldState.ChannelID}
		updateDetails(newState, usageKey, revisedAmount)
		if newState.UsedAmount.Cmp(oldState.PlannedAmount.Add(oldState.PlannedAmount, oldState.RefundAmount)) > 0 {
			return nil, fmt.Errorf("Usage Exceeded on channel Id %v", oldState.ChannelID)
		}
		return BuildOldAndNewValuesForCAS(newState)

	}
	//Make sure you update the planned amount ONLY when the new value is greater than what was last persisted
	IncrementPlannedAmount ConditionFunc = func(conditionValues []TypedKeyValueData, revisedAmount *big.Int, channelId *big.Int) (newValues []TypedKeyValueData, err error) {
		oldState, err := convertTypedDataToPrePaidUsage(conditionValues)
		if err != nil {
			return nil, err
		}

		oldState.ChannelID = channelId
		newState := oldState.Clone()
		usageKey := PrePaidDataKey{UsageType: PLANNED_AMOUNT, ChannelID: oldState.ChannelID}
		updateDetails(newState, usageKey, revisedAmount)
		return BuildOldAndNewValuesForCAS(newState)

	}
	//If there is no refund amount yet, put it , else add latest value in DB with the additional refund to be done
	IncrementRefundAmount ConditionFunc = func(conditionValues []TypedKeyValueData, revisedAmount *big.Int, channelId *big.Int) (newValues []TypedKeyValueData, err error) {
		newState, err := convertTypedDataToPrePaidUsage(conditionValues)
		if err != nil {
			return nil, err
		}
		newState.ChannelID = channelId
		usageKey := PrePaidDataKey{UsageType: REFUND_AMOUNT, ChannelID: newState.ChannelID}
		updateDetails(newState, usageKey, revisedAmount)
		return BuildOldAndNewValuesForCAS(newState)

	}
)

type FreeCallPayment added in v1.1.1

type FreeCallPayment struct {
	//Has the Id of the user making the call
	UserId string
	//Service Id .
	ServiceId string
	//Organization Id
	OrganizationId string
	//Current block number
	CurrentBlockNumber *big.Int
	// Signature passed
	Signature []byte
	//Group ID
	GroupId string
	//Auth Token Passed
	AuthToken []byte
	//Token expiration date in blocks
	AuthTokenExpiryBlockNumber *big.Int
}

To Support Free calls

func (*FreeCallPayment) String

func (key *FreeCallPayment) String() string

type FreeCallPaymentValidator added in v1.1.1

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

func NewFreeCallPaymentValidator added in v1.1.1

func NewFreeCallPaymentValidator(funcCurrentBlock func() (currentBlock *big.Int, err error), signer common.Address) *FreeCallPaymentValidator

func (*FreeCallPaymentValidator) Validate added in v1.1.1

func (validator *FreeCallPaymentValidator) Validate(payment *FreeCallPayment) (err error)

type FreeCallStateService

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

func (*FreeCallStateService) GetFreeCallsAvailable

func (service *FreeCallStateService) GetFreeCallsAvailable(context context.Context,
	request *FreeCallStateRequest) (reply *FreeCallStateReply, err error)

type FreeCallTransaction

type FreeCallTransaction interface {
	FreeCallUser() *FreeCallUserData

	Commit() error

	Rollback() error
}

type FreeCallUserData

type FreeCallUserData struct {
	UserId         string
	FreeCallsMade  int
	OrganizationId string
	ServiceId      string
	GroupID        string
}

func (*FreeCallUserData) String

func (data *FreeCallUserData) String() string

type FreeCallUserKey

type FreeCallUserKey struct {
	UserId         string
	OrganizationId string
	ServiceId      string
	GroupID        string
}

func (*FreeCallUserKey) String

func (key *FreeCallUserKey) String() string

type FreeCallUserService

type FreeCallUserService interface {
	GetFreeCallUserKey(payment *FreeCallPayment) (userKey *FreeCallUserKey, err error)

	//if the user details are not found, send back a new entry to be persisted
	FreeCallUser(key *FreeCallUserKey) (freeCallUser *FreeCallUserData, ok bool, err error)

	ListFreeCallUsers() (freeCallUsers []*FreeCallUserData, err error)

	StartFreeCallUserTransaction(payment *FreeCallPayment) (transaction FreeCallTransaction, err error)
}

func NewFreeCallUserService

func NewFreeCallUserService(
	storage *FreeCallUserStorage,

	locker Locker,
	groupIdReader func() ([32]byte, error), metadata *blockchain.ServiceMetadata) FreeCallUserService

type FreeCallUserStorage

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

func NewFreeCallUserStorage

func NewFreeCallUserStorage(atomicStorage AtomicStorage) *FreeCallUserStorage

func (*FreeCallUserStorage) CompareAndSwap

func (storage *FreeCallUserStorage) CompareAndSwap(key *FreeCallUserKey, prevState *FreeCallUserData, newState *FreeCallUserData) (ok bool, err error)

func (*FreeCallUserStorage) Get

func (storage *FreeCallUserStorage) Get(key *FreeCallUserKey) (state *FreeCallUserData, ok bool, err error)

func (*FreeCallUserStorage) GetAll

func (storage *FreeCallUserStorage) GetAll() (states []*FreeCallUserData, err error)

func (*FreeCallUserStorage) Put

func (storage *FreeCallUserStorage) Put(key *FreeCallUserKey, state *FreeCallUserData) (err error)

func (*FreeCallUserStorage) PutIfAbsent

func (storage *FreeCallUserStorage) PutIfAbsent(key *FreeCallUserKey, state *FreeCallUserData) (ok bool, err error)

type FreeCallUserUpdate

type FreeCallUserUpdate func(user *FreeCallUserData)
var (
	IncrementFreeCallCount FreeCallUserUpdate = func(user *FreeCallUserData) {
		user.FreeCallsMade = user.FreeCallsMade + 1
	}
)

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(pricing *pricing.PricingStrategy) (validator IncomeValidator)

NewIncomeValidator returns new income validator instance

type KeyValueData

type KeyValueData struct {
	Key     string
	Value   string
	Present bool
}

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, paymentStorage *PaymentStorage, metaData *blockchain.ServiceMetadata) *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. Simple case current_nonce == blockchain_nonce unspent_amount = blockchain_value - current_signed_amount Complex case current_nonce != blockchain_nonce Taking into account our assumptions, we know that current_nonce = blockchain_nonce + 1.

unspent_amount = blockchain_value - oldnonce_signed_amount - current_signed_amount It should be noted that in this case the server could send us smaller old nonce_signed_amount (not the actually last one which was used for channelClaim). In this case, the server can only make us believe that we have more money in the channel then we actually have. That means that one possible attack via unspent_amount is to make us believe that we have less tokens than we truly have, and therefore reject future calls (or force us to call channelAddFunds).

func (*PaymentChannelStateService) StorageNonceMatchesWithBlockchainNonce added in v1.0.0

func (service *PaymentChannelStateService) StorageNonceMatchesWithBlockchainNonce(storageChannel *PaymentChannelData) (equal bool, err error)

verifies whether storage channel nonce is equal to blockchain nonce or not

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) Get added in v1.0.0

func (storage *PaymentStorage) Get(paymentID string) (payment *Payment, ok bool, 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 PrePaidData

type PrePaidData struct {
	Amount *big.Int
}

Kept the bare minimum here , other details like group and sender address of this channel can always be retrieved from BlockChain

func (*PrePaidData) String

func (data *PrePaidData) String() string

type PrePaidDataKey

type PrePaidDataKey struct {
	ChannelID *big.Int
	UsageType string
}

func (*PrePaidDataKey) String

func (key *PrePaidDataKey) String() string

type PrePaidPayment

type PrePaidPayment struct {
	ChannelID      *big.Int
	OrganizationId string
	GroupId        string
	AuthToken      string
}

To Support PrePaid calls and also concurrency

func (*PrePaidPayment) String

func (payment *PrePaidPayment) String() string

Used when the Request comes in

type PrePaidPaymentHandler

type PrePaidPaymentHandler struct {
	PrePaidPaymentValidator *PrePaidPaymentValidator
	// contains filtered or unexported fields
}

func (*PrePaidPaymentHandler) Complete

func (h *PrePaidPaymentHandler) Complete(payment handler.Payment) (err *handler.GrpcError)

Just logging , as we increase the usage before calling the service assuming the service call will be successful

func (*PrePaidPaymentHandler) CompleteAfterError

func (h *PrePaidPaymentHandler) CompleteAfterError(payment handler.Payment, result error) (err *handler.GrpcError)

func (*PrePaidPaymentHandler) Payment

func (h *PrePaidPaymentHandler) Payment(context *handler.GrpcStreamContext) (transaction handler.Payment,
	err *handler.GrpcError)

func (*PrePaidPaymentHandler) Type

func (h *PrePaidPaymentHandler) Type() (typ string)

type PrePaidPaymentValidator

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

func NewPrePaidPaymentValidator

func NewPrePaidPaymentValidator(pricing *pricing.PricingStrategy, manager token.Manager) *PrePaidPaymentValidator

func (*PrePaidPaymentValidator) Validate

func (validator *PrePaidPaymentValidator) Validate(payment *PrePaidPayment) (err error)

type PrePaidService

type PrePaidService interface {
	GetUsage(key PrePaidDataKey) (*PrePaidData, bool, error)
	UpdateUsage(channelId *big.Int, revisedAmount *big.Int, updateUsageType string) error
}

func NewPrePaidService

func NewPrePaidService(
	storage TypedAtomicStorage,
	prepaidValidator *PrePaidPaymentValidator, groupIdReader func() ([32]byte, error)) PrePaidService

type PrePaidTransaction

type PrePaidTransaction interface {
	ChannelId() *big.Int
	Price() *big.Int
	Commit() error
	Rollback() error
}

type PrePaidUsageData

type PrePaidUsageData struct {
	ChannelID       *big.Int
	PlannedAmount   *big.Int
	UsedAmount      *big.Int
	RefundAmount    *big.Int
	UpdateUsageType string
}

This will ony be used for doing any business checks

func (PrePaidUsageData) Clone

func (data PrePaidUsageData) Clone() *PrePaidUsageData

func (*PrePaidUsageData) GetAmountForUsageType

func (data *PrePaidUsageData) GetAmountForUsageType() (*big.Int, error)

func (*PrePaidUsageData) String

func (data *PrePaidUsageData) String() string

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 NewPrefixedAtomicStorage

func NewPrefixedAtomicStorage(atomicStorage AtomicStorage, prefix string) *PrefixedAtomicStorage

It is recommended to use this function to create a PrefixedAtomicStorage

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) CompleteTransaction

func (storage *PrefixedAtomicStorage) CompleteTransaction(transaction Transaction, update []KeyValueData) (ok bool, err error)

func (*PrefixedAtomicStorage) Delete

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

func (*PrefixedAtomicStorage) ExecuteTransaction

func (storage *PrefixedAtomicStorage) ExecuteTransaction(request CASRequest) (ok bool, 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

func (*PrefixedAtomicStorage) StartTransaction

func (storage *PrefixedAtomicStorage) StartTransaction(conditionKeys []string) (transaction Transaction, err error)

type ProviderControlService added in v0.1.5

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

func NewProviderControlService added in v0.1.5

func NewProviderControlService(channelService PaymentChannelService, serMetaData *blockchain.ServiceMetadata,
	orgMetadata *blockchain.OrganizationMetaData) *ProviderControlService

func (*ProviderControlService) GetListInProgress added in v0.1.5

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 added in v0.1.5

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 added in v0.1.5

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

func (*ProviderControlService) StartClaimForMultipleChannels

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

We need to have an ability to StartClaims for multiple channels too! The User makes a Daemon call to the get all the pending claims The user then needs to call the start claim for every channel that he intends to claim ( thus a new signature again ) for every invocation of StartClaim ! PS You can make Multiple Claims in BlockChain in a single call multiChannelClaim You can now initiate multiple claims using this function StartClaimsOnMultipleChannels that takes a list of ChannelIds , What Daemon will do is invoke the StartClaim internally for every channel Id passed If an error is encountered , then we return back whatever was successful and stop with the channel ID that had an issue and return the error that was encountered.

type TokenService

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

func NewTokenService

func NewTokenService(paymentChannelService PaymentChannelService,
	usageService PrePaidService, tokenManager token.Manager, validator *ChannelPaymentValidator, metadata *blockchain.ServiceMetadata) *TokenService

func (*TokenService) GetToken

func (service *TokenService) GetToken(ctx context.Context, request *TokenRequest) (reply *TokenReply, err error)

type Transaction

type Transaction interface {
	GetConditionValues() ([]KeyValueData, error)
}

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)
	ExecuteTransaction(request TypedCASRequest) (ok bool, err error)
}

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

func NewPrepaidStorage

func NewPrepaidStorage(atomicStorage AtomicStorage) TypedAtomicStorage

NewPrepaidStorage returns new instance of TypedAtomicStorage

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) ExecuteTransaction

func (storage *TypedAtomicStorageImpl) ExecuteTransaction(request TypedCASRequest) (ok bool, 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

type TypedCASRequest

type TypedCASRequest struct {
	RetryTillSuccessOrError bool
	Update                  TypedUpdateFunc
	ConditionKeys           []interface{} //Typed Keys
}

type TypedKeyValueData

type TypedKeyValueData struct {
	Key     interface{}
	Value   interface{}
	Present bool
}

func BuildOldAndNewValuesForCAS

func BuildOldAndNewValuesForCAS(data *PrePaidUsageData) (newValues []TypedKeyValueData, err error)

type TypedTransaction

type TypedTransaction interface {
	GetConditionValues() ([]TypedKeyValueData, error)
}

type TypedUpdateFunc

type TypedUpdateFunc func(conditionValues []TypedKeyValueData) (update []TypedKeyValueData, ok bool, err error)

Best to change this to KeyValueData , will do this in the next commit

type UpdateFunc

type UpdateFunc func(conditionValues []KeyValueData) (update []KeyValueData, ok bool, err error)

Best to change this to KeyValueData , will do this in the next commit

Jump to

Keyboard shortcuts

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