Authors: Marcin Benke, Łukasz Gleń
Thanks to María Paula Fernández
With Golem you can exchange computational power, as a commodity or a service for GNT. These are market transactions. The different parties (users) and transactions are part of a small economy.
Within the Golem economy, we are free to define the rules and regulations for it. Our goal, however, is for it to be similar to real-life economies: demand, supply and quality affecting prices should always be included. This economy works in an anonymous and distributed network, which adds a layer of complexity to it. Golem is not a stock market, there is no central point to place bids and offers. Everyone must make their deals on a p2p basis and on their best criteria. When the Golem Network goes live, its economy goes live as well: we cannot modify any rules or regulations, nor can we affect the price, supply, and demand, and we cannot guarantee the behavior of parties. It is desired to define this economy in detail right at the start, to suppress — or at least mitigate to a bare minimum — attacks to destabilize the economy, as well as prevent abuses and frauds.
We have split this text: the first part tells you what the Brass Golem marketplace is, the second part contains raw details.
Part I, The marketplace concept
A game, rules, and players
First of all, let us stress the distinction between a transaction framework and client strategies.
A transaction framework consists of all common rules governing the market, such as: legal restrictions, regulations, technologies, platforms, protocols etc; a set of rules that is not to be changed and common to all participants. Some examples can be stock markets, auctions, shopping or even a recruitment process.
On distributed markets, it boils down to defining the protocol — the system of strict rules and message formats for communication between parties; there are no additional governing services provided. While investigating the transactions’ nature in Golem, we concluded that the resemblance to tenders is notorious, however, Golem transactions still have their own unique features.
In general, first a requestor publishes a new tender for computing a task; then providers send offers with their prices; and afterward the requestor selects the most suitable providers, which then compute the task.
A strategy is the individual way a client acts on the market with respect to the transaction framework. It includes price negotiation, agreement conditions and a counterparty choice. Strategies can change frequently on a live market.
All market behaviors are automated by algorithms. We provide default algorithms within Golem clients. It is possible to provide your own algorithm as it is possible to develop your own Golem client. But it is not easy and most users will use the default algorithms. To ensure the stability of the Golem economy, our default algorithms need to be robust, efficient, secure and react to supply and demand changes.
Bear in mind that the Golem Network is a distributed market. There is no global information on the current average prices, supply and demand, transactions, service quality, fairness, threats or other events. From a client point of view, provider or requestor, there is no knowledge of the totality of the network, a client can only rely on its local information: the local history of its transactions. Client strategies, algorithms, are based only on a price and local reputation of the counterparty.
A requestor may choose providers for a given task based on their reputation (reflecting past performance) and the price offered. Usually these factors are opposed and preference for them may vary from one requestor to another. However, we can attempt to characterize it by price sensitivity, and compute the provider score as a weighted average between price and performance.
The provider’s reputation is based on two factors: its efficiency (computation speed) and efficacy (the fraction of tasks computed successfully). Both are subject to history smoothing so that recent performance has more impact than past one.
A provider is interested in maximizing its effective price per hour. Hence, the main variable is the expected revenue per hour.
In Golem, payments are based on subtask timeouts as set by the requestor, rather than actual computation time. Consequently, the effective price per hour can again be expressed in terms of nominal price and two factors: first, the ratio of requestor’s timeout to provider’s computation time, and, secondly, the ratio of work paid to the work done (please note that work can remain unpaid for a number of reasons — but the end result stays the same).
The price varies alongside the varying demand and supply of computational power. On the other hand, as noted earlier, an individual requestor has very little knowledge of the current demand, supply and hence, the price.
What they are able to know is the last job’s payment, however it might not be an indication, since market conditions might have changed in time.
However, they should observe the following: if they can’t get a job for a period of time, perhaps the price is too high; conversely, if they are getting lots of work, maybe it would be good to increase the price.
The effective price per hour consists of the minimal price m (for instance operating costs — do not change in time) and the expected profit per hour f. It is proposed that the expected profit falls exponentially with the provider’s “thirst for work” (tₓ - time spent unemployed)
and rises exponentially with the time spent employed (tₑ- subtask computation time)
Hence the final offer price calculation takes into account the requestor’s reputation: the offer price for requestors with low reputation is higher.
We have run several (actually several hundred) simulations to evaluate the robustness and stability of our algorithms. The providers are generated in a Poisson process with their performances drawn from a lognormal distribution based on benchmark data gathered by the Golem monitor; while requestors repeatedly offer tasks of varying difficulty.
The results were mostly according to our expectations: those providers with lower costs and better performance get more work and more profit, while underperforming and overpriced providers get little (if any) work.
We have also simulated some adversarial scenarios, for example, providers cheating on their benchmarks — or evil providers undertaking work but never completing it. Such providers are bound to get some work initially but were weeded out soon.
The market description we have presented here has been simplified to make it brief and easier to understand. However, we have had to skip some details, for instance: constraints, the relation to our Concent service and its impact on the Golem protocol. We have only focused on the economic model, concepts and our approach to the marketplace.
Implementation works are underway. We are set to deliver this new marketplace in a matter of weeks. However, as the Golem ecosystem grows and brings new requirements, the work into the model improvement and the development of new models is not stopping anytime soon. Our next step is to provide an anti-sybil system to improve the security and fairness of the marketplace.
Part II, The nitty-gritty details
- A subtask is a subject of an agreement. In other words, the requestor pays for a subtask, not for used computational power. The consequence is that the value of the payment is set before computations start.
- The following requestor’s estimation holds: a node with min_perfperformance completes the subtask in subtask_timeout time.
Conceptual protocol description
- A requestor broadcasts a public message on the new task to be computed. TaskHeader contains: max_price, subtask_timeout, min_perf.
- An interested provider sends a direct message to requestor. WantToComputeTask contains: the offer price and provider performance.
- The requestor collects offers and selects providers. It sends a direct message-agreement to the selected provider. TaskToCompute contains: offer price and subtask_timeout.
- After receiving TaskToCompute, a provider can immediately cancel its offer or start to compute. Upon the computation completion, the subtask status is: timeout, failed or reported (to the requestor).
- A reported subtask is being verified by requestor. After that, a subtask status is: rejected, waiting for payment, paid or overdue.
The provider is interested in maximizing its effective price per hour.
From a provider’s point of view, requestor reputation depends on how fast it’s tasks can be computed, and how much of the work done gets paid. It consists of three factors:
1) R — relative efficiency. After each completed subtask, this factor gets updated with relative computation velocity:
where ψ is history forgetting (=0.9 by default).
2) Vₐ — sum of all subtask values assigned to the provider. This factor is not a subject to history forgetting.
3) Vₚ — sum of all paid subtask prices. This factor is not a subject to history forgetting.
Provider calculates its effective price per hour r as
where m is the provider’s minimal price per hour (for instance, operating costs, depending on the provider), and f is the calculated expected profit (does not depend on the requestor). Both r and f change in time. We propose that the expected profit falls according to the provider’s “thirst for work” (time spent unemployed)
where ∆t is the time of unemployment and rises with the time spent employed
where ∆t is subtask computation time. Constants α and β are factors of change velocity.
Provider calculates the offer price p (depends on requestor) as
where S is requestor score given by
where Q is requestor payment rate with
where c is a credit — tolerance for (temporarily) unpaid work (=m by default).
A requestor’s goal is to minimize prices and maximize quality.
A provider reputation is based on two factors: its efficiency R — computation speed, and efficacy Q — a fraction of subtasks computed successfully.
The efficacy is represented by a quality vector Q = (s,t,f,r), consisting of rates of success (positive requestor verification outcome), timeout, failed (other than timeout) and rejected (due to negative requestor verification outcome or no results).
Both are subject to history forgetting ψ (=0.9 by default) so that the recent performance has more impact than performance far in the past.
After each completed subtask, the efficiency factor gets updated with the relative computation velocity of this subtask:
And the quality factor gets updated according to the subtask outcome, e.g. for success
The requestor sets the price sensitivity factor σ∈[0,1] — its preference for low prices against high reputation. A score Sᵢ is computed for each provider i
where pᵢ is the provider’s offer price, P is the requestor’s max_price and qᵢ is quality factor representing success ratio calculated from the efficacy
where d≥1 is the distrust factor towards unknown providers (=5 by default) and
is maximal value of q, therefore it normalizes q.
The default provider selection function is greedy policy — providers with the highest scores are selected.
We are aware this blogpost seems complex, but we hope the first section helps you understand Golem when the new marketplace is introduced. In short, the biggest change we made is providing a tender-like approach instead of fixed price and FIFO task assignment. This allows us to consider both providers’ and requestors’ strategies. We provided default algorithms but they can be and will be improved in the future.
If you have any questions or feedback, please do not hesitate to contact us. We are building this better, and fairer marketplace for you so your feedback is crucial.