- a subset of the node state flags and fields can be persisted in a database
- a flag is persistent if
NodeStateFlag.persistent
is set - a field is persistent if
encode
anddecode
are not nil - persistent flags and fields are created with a separate constructor
- a flag is persistent if
- stored states are loaded during startup
- in-memory states that have been changed since loading the stored version or newly created ones with no stored version are considered "dirty" until they are saved (again)
INFO [06-03|01:17:56.023] Imported new block headers count=1 elapsed=3.429ms number=10189345 hash="3560fb…8bbae5" | |
INFO [06-03|01:17:57.551] Looking for peers peercount=2 tried=8 static=0 | |
INFO [06-03|01:18:06.389] Imported new block headers count=1 elapsed=10.590ms number=10189346 hash="0fc3d7…39d77d" | |
INFO [06-03|01:18:07.553] Looking for peers peercount=2 tried=11 static=0 | |
INFO [06-03|01:18:17.556] Looking for peers peercount=2 tried=12 static=0 | |
INFO [06-03|01:18:18.846] Imported new block headers count=1 elapsed=8.864ms number=10189347 hash="004ea0…1aa5e7" | |
INFO [06-03|01:18:27.559] Looking for peers peercount=2 tried=8 static=0 | |
INFO [06-03|01:18:45.564] Imported new block headers count=1 elapsed=9.115ms number=10189348 hash="30b581…41ad96" | |
INFO [06-03|01:19:00.867] Imported new block headers count=1 elapsed=9.135ms number=101893 |
WeightedRandomSelect
is a passive, not thread-safe data structure that holds a set of items with assigned selection weights and can quickly select one of them randomly. Weights are specified by a callback function but the last known weights are also stored in the data structure. If the weight increases compared to the last returned value then it should be explicitly updated. If it decreases then update happens automatically.
NodeStateMachine
connects different system components operating on subsets of network nodes. It can be considered an enhanced version of les.clientPeerSet
/ les.serverPeerSet
which it could probably replace over time. Node states are represented by uint64
bit vectors with each bit assigned to a state flag. Each state flag has a string name and the mapping is created automatically. It is possible to subscribe to subsets of state flags and receive a callback if one of the nodes has a relevant state flag c
The lesPay
token sale model uses service tokens that continuously "expire" under certain conditions, meaning their value is reduced exponentially over time. Expiration happens when some amount of free connection is possible and therefore all existing tokens are spendable. Expiration can be interpreted as a kind of "spendability" fee that incentivizes clients to indeed spend their tokens in a limited time frame. This can be realized in two ways:
- with "inflationary" units; if all prices rise exponentially then value of existing tokens is reduced inversely
- with "stable tokens"; if the nominal value of each token is stable then the token balances should be reduced continuously
The second interpretation fits with the model better because service tokens (which are basically a promise from the server) are meant to have a more or less predictable purchasing power. With stable token nominations the client can expect the prices to not change qui
package main | |
import ( | |
"fmt" | |
"math" | |
"sort" | |
) | |
const ( | |
maxLevel = 10 |
createDeposit(amount map[common.Address]uint64) depositID
- sends a transaction to create a new deposit with the given target allowances
subscribeDepositEvents(ch chan struct {id depositID, state int})
- sends an event to the given channel every time a deposit goes into
pending
,active
orexpired
state
- sends an event to the given channel every time a deposit goes into
estimatedExpiry(id depositID) time.Duration
- returns the estimated remaining time while cheques can still be written using this deposit
allowancesLeft(id depositID) map[common.Address]uint64
lastCheque(id depositID, to common.Address) (totalSpent, allowanceLeft uint64)
writeCheque(id depositID, to common.Address, amount uint64) (totalSpent, allowanceLeft uint64, proofOfPayment []byte)
- creates a cheque if the deposit is in
active
state and there is enough allowance left (otherwiseproofOfPayment
should benil
)
- creates a cheque if the deposit is in
It is possible to do simple probabilistic one-to-many payments with one condition: the set of potential recipients and their assigned probabilities should be decided when creating the payment contract. This is actually a very good fit for light client incentivization. A client can collect many potential recipients (anyone who provided free service) but cannot really know how a particular server will actually react to receiving payments and whether it is worth paying for over the long term. Starting with very small payments is preferable. A one-to-one channel can limit the amount redeemable at the receiver side but the sender still has to pay transaction costs to build a payment route to every new potential receiver. Therefore it has to expect a high amount of free service from every server before risking the first payment. This could make the bootstrapping process for clients slow and/or expensive. One the other hand the proposed method could build a p
LES in-protocol payments can be sent using multiple payment technologies or even multiple currencies. These are realized as plug-in modules. The payment sender module generates a "proof of payment" that the receiver module can interpret and verify. These proofs can be transmitted through an LES connection or LESTALK UDP messages.
Note: the design allows using multiple currencies on both the client and server side. Each payment module uses one specific currency but it can handle value conversions on both ends. In the first implementation we won't allow this though, the first payment module should only handle ETH. This makes value calculations a lot easier for requestPayment
and paymentCost
. Expected transaction costs have to be considered but that can be very simple too (hardcoded gas cost, user specified gas price).
func receivePayment(from enode.ID, proofOfPayment, oldMeta []byte) (value uint64, newMeta []byte, err error)
title | sort_key |
---|---|
les Namespace |
C |
The les
API allows you to manage LES server settings, including client parameters and payment settings for prioritized clients. It also provides functions to query checkpoint information in both server and client mode.
- TOC {:toc}
ServerInfo() map[string]interface{}
: query server info
minimumCapacity
: minimum allowed capacity for any clientfreeClientCapacity
: capacity assigned to free (unknown, non-priority) clientstotalCapacity
: total allowed capacity of simultaneously connected clients (may change dynamically during operation)totalConnectedCapacity
: total capacity of currently connected clientspriorityConnectedCapacity
: total capacity of currently connected priority clientstotalPriorityCapacity
: total capacity of all priority clients (may exceedtotalCapacity
in which case priority clients might be rejected too)
SetClientParams(ids []string, tags []string, params map[string]interface{}) error
: set certain parameter fields for each client whose id is in the ids
list or has all tags in the tags
list
userTags
: user tags assigned to the client