Advertisement

A True Concurrent Model of Smart Contracts Executions

Conference paper
Part of the Lecture Notes in Computer Science book series (LNCS, volume 12134)

Abstract

The development of blockchain technologies has enabled the trustless execution of so-called smart contracts, i.e. programs that regulate the exchange of assets (e.g., cryptocurrency) between users. In a decentralized blockchain, the state of smart contracts is collaboratively maintained by a peer-to-peer network of mutually untrusted nodes, which collect from users a set of transactions (representing the required actions on contracts), and execute them in some order. Once this sequence of transactions is appended to the blockchain, the other nodes validate it, re-executing the transactions in the same order. The serial execution of transactions does not take advantage of the multi-core architecture of modern processors, so contributing to limit the throughput. In this paper we propose a true concurrent model of smart contracts execution. Based on this, we show how static analysis of smart contracts can be exploited to parallelize the execution of transactions.

1 Introduction

Smart contracts [21] are computer programs that transfer digital assets between users without a trusted authority. Currently, smart contracts are supported by several blockchains, the first and most widespread one being Ethereum [9]. Users interact with a smart contract by sending transactions, which trigger state updates, and may possibly involve transfers of crypto-assets between the called contract and the users. The sequence of transactions on the blockchain determines the state of each contract, and the balance of each user.

The blockchain is maintained by a peer-to-peer network of nodes, which follow a consensus protocol to determine, at each turn, a new block of transactions to be added to the blockchain. This protocol guarantees the correct execution of contracts also in the presence of (a minority of) adversaries in the network, and ensures that all the nodes have the same view of their state. Nodes play the role of miner or that of validator. Miners gather from the network sets of transactions sent by users, and execute them serially to determine the new state. Once a block is appended to the blockchain, validators re-execute all its transactions, to update their local view of the contracts state and of the users’ balance. To do this, validators process the transactions exactly in the same order in which they occur in the block, since choosing a different order could potentially result in inconsistencies between the nodes (note that miners also act as validators, since they validate all the blocks received from the network).

Although executing transactions in a purely sequential fashion is quite effective to ensure the consistency of the blockchain state, in the age of multi-core processors it fails to properly exploit the computational capabilities of nodes. By enabling miners and validators to concurrently execute transactions, it would be possible to improve the efficiency and the throughput of the blockchain.

This paper exploits techniques from concurrency theory to provide a formal backbone for parallel executions of transactions. More specifically, our main contributions can be summarised as follows:
  • As a first step, we formalise blockchains, giving their semantics as a function which maps each contract to its state, and each user to her balance. This semantics reflects the standard implementation of nodes, where transactions are evaluated in sequence, without any concurrency.

  • We introduce two notions of swappability of transactions. The first is purely semantic: two adjacent transactions can be swapped if doing so preserves the semantics of the blockchain. The second notion, called strong swappability, is more syntactical: it checks a simple condition (inspired by Bernstein’s conditions [7]) on static approximations of the variables read/written by the transactions. Theorem 2 shows that strong swappability is strictly included in the semantic relation. Further, if we transform a blockchain by repeatedly exchanging adjacent strongly swappable transactions, the resulting blockchain is observationally equivalent to the original one (Theorem 4).

  • Building upon strong swappability, we devise a true concurrent model of transactions execution. To this purpose, we transform a block of transactions into an occurrence net, describing exactly the partial order induced by the swappability relation. We model the concurrent executions of a blockchain in terms of the step firing sequences (i.e. finite sequences of sets of transitions) of the associated occurrence net. Theorem 5 establishes that the concurrent executions and the serial one are semantically equivalent.

  • We describe how miners and validators can use our results to concurrently execute transactions, exploiting the multi-core architecture available on their nodes. Remarkably, our technique is compatible with the current implementation of the Ethereum blockchain, while the other existing approaches to parallelize transactions execution would require a soft-fork.

  • We apply our technique to ERC-721 tokens, one of the most common kinds of contracts in Ethereum, showing them to be suitable for parallelization.

Because of space constraints, all the proofs of our results are in [6].

2 Transactions and Blockchains

In this section we introduce a general model of transactions and blockchains, abstracting from the actual smart contracts language.

A smart contract is a finite set of functions, i.e. terms of the form Open image in new window, where Open image in new window is a function name, \(\varvec{x_{}}\) is the sequence of formal parameters (omitted when empty), and Open image in new window is the function body. We postulate that the functions in a contract have distinct names. We abstract from the actual syntax of Open image in new window, and we just assume that the semantics of function bodies is defined (see e.g. [5] for a concrete instance of syntax and semantics of function bodies).

Let Open image in new window be a set of values, ranged over by Open image in new window, let Open image in new window be a set of constant names \(x_{}, y_{}, \ldots \), and let Open image in new window be a set of addresses Open image in new window, partitioned into account addresses Open image in new window and contract addresses Open image in new window. We assume a mapping Open image in new window from addresses to contracts.

We assume that each contract has a key-value store, which we render as a partial function Open image in new window from keys Open image in new window to values. The state of the blockchain is a function Open image in new window from addresses to key-value stores. We postulate that Open image in new window for all Open image in new window. A qualified key is a term of the form Open image in new window. We write Open image in new window for Open image in new window; when Open image in new window, we write Open image in new window. We use \({p}_{},{q}_{},\ldots \) to range over qualified keys, \(P_{},Q_{},\ldots \) to range over sets of them, and \(\mathbb {P}\) to denote the set of all qualified keys.

To have a uniform treatment of accounts and contracts, we assume that for all account addresses Open image in new window, Open image in new window, and that the contract Open image in new window has exactly one function, which just skips. In this way, the statement Open image in new window, which transfers n currency units to Open image in new window, can be rendered as a call to this function.

State updates define how values associated with qualified keys are modified.

Definition 1 (State update)

A state update Open image in new window is a function from qualified keys to values; we denote with Open image in new window the state update which maps Open image in new window to Open image in new window. We define \({\text {keys}}({\pi _{}})\) as the set of qualified keys Open image in new window such that Open image in new window and Open image in new window. We apply updates to states as follows:

We denote with Open image in new window the semantics of the statement Open image in new window. This semantics is either a blockchain state \(\sigma _{}'\), or it is undefined (denoted by \(\bot \)). The semantics is parameterised over a state \(\sigma _{}\), an address Open image in new window (the contract wherein Open image in new window is evaluated), and an environment Open image in new window, used to evaluate the formal parameters and the special names Open image in new window and Open image in new window. These names represent, respectively, the caller of the function, and the amount of currency transferred along with the call. We postulate that Open image in new window and Open image in new window are not used as formal parameters.

We define the auxiliary operators \(+\) and − on states as follows:i.e., Open image in new window updates \(\sigma _{}\) by increasing the Open image in new window of Open image in new window of Open image in new window currency units.
A transaction Open image in new window is a term of the form:Intuitively, Open image in new window is the address of the caller, Open image in new window is the address of the called contract, Open image in new window is the called function, n is the value transferred from Open image in new window to Open image in new window, and Open image in new window is the sequence of actual parameters. We denote the semantics of Open image in new window in \(\sigma _{}\) as Open image in new window, where the function Open image in new window is defined in Fig. 1, which we briefly comment.
Fig. 1.

Semantics of transactions.

The semantics of a transaction Open image in new window, in a given blockchain state \(\sigma _{}\), is a new state \(\sigma _{}'\). Rule [Tx1] handles the case where the transaction is successful: this happens when Open image in new window’s balance is at least Open image in new window, and the function call terminates in a non-error state. Note that Open image in new window units of currency are transferred to Open image in new window before starting to execute Open image in new window, and that the names Open image in new window and Open image in new window are bound, respectively, to Open image in new window and Open image in new window. Rule [Tx2] applies either when Open image in new window’s balance is not enough, or the execution of Open image in new window fails. In these cases, Open image in new window does not alter the state.

A blockchain Open image in new window is a finite sequence of transactions; we denote with Open image in new window the empty blockchain. The semantics of a blockchain is obtained by folding the semantics of its transactions, starting from a given state \(\sigma \):Note that erroneous transactions can occur within a blockchain, but they have no effect on its semantics (as rule [Tx2] makes them identities w.r.t. the append operation). We assume that in the initial state of the blockchain, denoted by \(\sigma ^{\star }\), each address Open image in new window has a balance Open image in new window, while all the other keys are unbound.

We write Open image in new window for Open image in new window, where Open image in new window. We say that a state \(\sigma _{}\) is reachable if Open image in new window for some Open image in new window.

Example 1

Consider the following functions of a contract at address Open image in new window:Let \(\sigma _{}\) be a state such that Open image in new window, and let Open image in new window, where:By applying rule [Tx1] three times, we have that:Summing up, Open image in new window. \(\diamond \)

3 Swapping Transactions

We define two blockchain states to be observationally equivalent when they agree on the values associated to all the qualified keys. Our formalisation is parameterised on a set of qualified keys \(P_{}\) over which we require the agreement.

Definition 2 (Observational equivalence)

For all \({P_{}\subseteq \mathbb {P}}\), we define \(\sigma _{}\sim _{P_{}} \sigma _{}'\) iff \(\forall {p}_{}\in P_{}: \sigma _{}{p}_{}= \sigma _{}'{p}_{}\). We say that \(\sigma _{}\) and \(\sigma _{}'\) are observationally equivalent, in symbols \(\sigma _{}\sim \sigma _{}'\), when \(\sigma _{}\sim _{P_{}} \sigma _{}'\) holds for all \(P_{}\). \(\diamond \)

Lemma 1

For all \(P_{},Q_{}\subseteq \mathbb {P}\): (i) \(\sim _{P_{}}\) is an equivalence relation; (ii) if \(\sigma _{}\sim _{P_{}} \sigma _{}'\) and \(Q_{}\subseteq P_{}\), then \(\sigma _{}\sim _{Q_{}} \sigma _{}'\); (iii) \(\sim \, = \, \sim _{\mathbb {P}}\). \(\diamond \)

We extend the equivalence relations above to blockchains, by passing through their semantics. For all \(P_{}\), we define Open image in new window iff Open image in new window holds for all reachable \(\sigma _{}\) (note that all the definitions and results in this paper apply to reachable states, since the unreachable ones do not represent actual contract executions). We write Open image in new window holds for all \(P_{}\). The relation \(\sim \) is a congruence with respect to the append operation, i.e. if Open image in new window then we can replace Open image in new window with Open image in new window in a larger blockchain, preserving its semantics.

Lemma 2

Open image in new window. \(\diamond \)

Two transactions are swappable when exchanging their order preserves observational equivalence.

Definition 3 (Swappability)

Two transactions Open image in new window are swappable, in symbols Open image in new window, when Open image in new window. \(\diamond \)

Example 2

Recall the transactions in Example 1. We have that Open image in new window and Open image in new window, but Open image in new window (see Fig. 5 in Appendix A of [6]). \(\diamond \)

We shall use the theory of trace languages originated from Mazurkiewicz’s works [17] to study observational equivalence under various swapping relations. Below, we fix the alphabet of trace languages as the set Open image in new window of all transactions.

Definition 4 (Mazurkiewicz equivalence)

Let I be a symmetric and irreflexive relation on Open image in new window. The Mazurkiewicz equivalence \(\simeq _{I}\) is the least congruence in the free monoid Open image in new window such that: Open image in new window: Open image in new window

Theorem 1 below states that the Mazurkiewicz equivalence constructed on the swappability relation \(\rightleftarrows \) is an observational equivalence. Therefore, we can transform a blockchain into an observationally equivalent one by a finite number of exchanges of adjacent swappable transactions.

Theorem 1

\(\simeq _{\rightleftarrows } \;\; \subseteq \;\; \sim \). \(\diamond \)

Example 3

We can rearrange the transactions in Example 1 as Open image in new window. Instead, Open image in new window (e.g., starting from a state \(\sigma _{}\) such that Open image in new window and Open image in new window, see Fig. 6 in Appendix A of [6]). \(\diamond \)

Note that the converse of Theorem 1 does not hold: indeed, Open image in new window requires that Open image in new window and Open image in new window have the same length, while Open image in new window may also hold for blockchains of different length (e.g., Open image in new window, where Open image in new window does not alter the state).

Safe Approximations of Read/Written Keys. Note that the relation \(\rightleftarrows \) is undecidable whenever the contract language is Turing-equivalent. So, to detect swappable transactions we follow a static approach, consisting of two steps. First, we over-approximate the set of keys read and written by transactions, by statically analysing the code of the called functions. We then check a simple condition on these approximations (Definition 7), to detect if two transactions can be swapped. Since static analyses to over-approximate read and written variables are quite standard [18], here we just rely on such approximations, by only assuming their safety. In Definition 5 we state that a set \(P_{}\) safely approximates the keys written by Open image in new window, when Open image in new window does not alter the state of the keys not in \(P_{}\). Defining set of read keys is a bit trickier: intuitively, we require that if we execute the transaction starting from two states that agree on the values of the keys in the read set, then these executions should be equivalent, in the sense that they do not introduce new differences between the resulting states (with respect to the difference already existing before).

Definition 5 (Safe approximation of read/written keys)

Given a set of qualified keys \(P_{}\) and a transaction Open image in new window, we define:

Example 4

Let Open image in new window, where Open image in new window is a function of Open image in new window. The execution of Open image in new window affects the Open image in new window of Open image in new window, Open image in new window and Open image in new window; however, Open image in new window is first incremented and then decremented, and so its value remains unchanged. Then, Open image in new window, and it is the smallest safe approximation of the keys written by Open image in new window. To prove that Open image in new window, assume two blockchains Open image in new window and Open image in new window and a set of keys Q such that Open image in new window and Open image in new window. If Open image in new window, then by [Tx2] we have Open image in new window. Since Open image in new window, then also Open image in new window, and so by [Tx2] we have Open image in new window. Then, Open image in new window. Otherwise, if Open image in new window, then by [Tx1] the execution of Open image in new window transfers one unit of currency from Open image in new window to Open image in new window, so the execution of Open image in new window affects exactly Open image in new window and Open image in new window. So, it is enough to show that Open image in new window implies Open image in new window for Open image in new window. For Open image in new window, we have that Open image in new window. For Open image in new window, we have that Open image in new window. Therefore, we conclude that Open image in new window. \(\diamond \)

Widening a safe approximation (either of read or written keys) preserves its safety; further, the intersection of two safe write approximations is still safe (see Lemma 6 in Appendix A of [6]). From this, it follows that there exists a least safe approximation of the keys written by a transaction.

Strong Swappability. We use safe approximations of the read/written keys to detect when two transactions are swappable. To achieve that, we check whether two transactions Open image in new window and Open image in new window operate on disjoint portions of the blockchain state. More specifically, we recast in our setting Bernstein’s conditions [7] for the parallel execution of processes: it suffices to check that the set of keys written by Open image in new window is disjoint from those written or read by Open image in new window, and vice versa. When this happens we say that the two transactions are strongly swappable.

Definition 6 (Strong swappability)

We say that two transactions Open image in new window are strongly swappable, in symbols Open image in new window, when there exist \(W,W',R,R' \subseteq \mathbb {P}\) such that Open image in new window, Open image in new window, Open image in new window, Open image in new window, and:
$$ \big ( R \cup W \big ) \cap W' \; = \; \emptyset \; = \; \big ( R' \cup W' \big ) \cap W \qquad \qquad \qquad \qquad {\diamond } $$

Example 5

Let Open image in new window and Open image in new window be functions of the contracts Open image in new window and Open image in new window, respectively, and consider the following transactions:where Open image in new window, Open image in new window, and Open image in new window are account addresses. To prove that Open image in new window, consider the following safe approximations of the written/read keys of Open image in new window and Open image in new window, respectively:Since \((W_1 \cup R_1) \cap W_2 = \emptyset = (W_2 \cup R_2) \cap W_1\), the two transactions are strongly swappable. Now, let:and consider the following safe approximations \(W_3\) and \(R_3\):Since \(W_1 \cap W_3 \ne \emptyset \ne W_2 \cap W_3\), then Open image in new window and Open image in new window. \(\diamond \)

The following theorem ensures the soundness of our approximation, i.e. that if two transactions are strongly swappable, then they are also swappable. The converse implication does not hold, as witnessed by Example 6.

Theorem 2

Open image in new window. \(\diamond \)

Example 6 (Swappable transactions, not strongly)

Consider the following functions and transactions of a contract at address Open image in new window:We prove that Open image in new window. First, consider a state \(\sigma _{}\) such that Open image in new window, Open image in new window, Open image in new window, Open image in new window and Open image in new window. We have that:In the second case, let \(\sigma _{}\) be such that Open image in new window, or Open image in new window, or Open image in new window, or Open image in new window. It is not possible that the guards in Open image in new window and Open image in new window are both true, so Open image in new window or Open image in new window raise an exception, leaving the state unaffected. Then, also in this case we have that Open image in new window, and so Open image in new window and Open image in new window are swappable. However, they are not strongly swappable if there exist reachable states Open image in new window such that Open image in new window. To see why, let Open image in new window. From the code of Open image in new window we see that \(W_1\) is the least safe over-approximation of the written keys of Open image in new window (Open image in new window). This means that every safe approximation of Open image in new window must include the keys of \(W_1\). Similarly, Open image in new window is the least safe over-approximation of the written keys of Open image in new window (Open image in new window). Since the least safe approximations of the keys written by Open image in new window and Open image in new window are not disjoint, Open image in new window does not hold. \(\diamond \)

Theorem 3 states that the Mazurkiewicz equivalence \(\simeq _{\#^{}_{}}\) is stricter than \(\simeq _{\rightleftarrows }\). Together with Theorem 1, if Open image in new window is transformed into Open image in new window by exchanging adjacent strongly swappable transactions, then Open image in new window and Open image in new window are observationally equivalent.

Theorem 3

\(\simeq _{\#^{}_{}} \; \subseteq \; \simeq _{\rightleftarrows }\). \(\diamond \)

Note that if the contract language is Turing-equivalent, then finding approximations which satisfy the disjointness condition in Definition 6 is not computable, and so the relation \(\#^{}_{}\) is undecidable.

Parameterised Strong Swappability. Strongly swappability abstracts from the actual static analysis used to obtain the safe approximations: it is sufficient that such an analysis exists. Definition 7 below parameterises strong swappability over a static analysis, which we represent as a function from transactions to sets of qualified keys, just requiring it to be a safe approximation. Formally, we say that Open image in new window is a static analysis of written keys when Open image in new window, for all Open image in new window; similarly, Open image in new window is a static analysis of read keys when Open image in new window, for all Open image in new window.

Definition 7 (Parameterised strong swappability)

Note that an effective procedure for computing Open image in new window and Open image in new window gives an effective procedure to determine whether two transactions are (strongly) swappable.

Lemma 3

For all static analyses Open image in new window and Open image in new window: (i) Open image in new window; (ii) if Open image in new window and Open image in new window are computable, then \(\#^{W}_{R}\) is decidable. \(\diamond \)

From the inclusion in item (i) of Lemma 3 and from Theorem 3 we obtain:

Theorem 4

\(\simeq _{\#^{W}_{R}} \; \subseteq \; \simeq _{\#^{}_{}} \; \subseteq \; \simeq _{\rightleftarrows }\). \(\diamond \)

4 True Concurrency for Blockchains

Given a swappability relation Open image in new window, we transform a sequence of transactions Open image in new window into an occurrence net Open image in new window, which describes the partial order induced by Open image in new window. Any concurrent execution of the transactions in Open image in new window which respects this partial order is equivalent to the serial execution of Open image in new window (Theorem 5).

From Blockchains to Occurrence Nets. We start by recapping the notion of Petri net [19]. A Petri net is a tuple \(\mathsf {N}= (\mathsf{P}, \mathsf{Tr}, \mathsf{{F}}, \mathsf{{m}_{0}})\), where \(\mathsf{P}\) is a set of places, \(\mathsf{Tr}\) is a set of transitions (with \(\mathsf{P}\cap \mathsf{Tr}= \emptyset \)), and \(\mathsf{{F}}: (\mathsf{P}\times \mathsf{Tr}) \cup (\mathsf{Tr}\times \mathsf{P}) \rightarrow \mathbb {N}\) is a weight function. The state of a net is a marking, i.e. a multiset \(\mathsf{{m}_{}}: \mathsf{P}\rightarrow \mathbb {N}\) defining how many tokens are contained in each place; we denote with \(\mathsf{{m}_{0}}\) the initial marking. The behaviour of a Petri net is specified as a transition relation between markings: intuitively, a transition \(\mathsf {t}_{}\) is enabled at \(\mathsf{{m}_{}}\) when each place \(\mathsf{{p_{}}}\) has at least \(\mathsf{{F}}(\mathsf{{p_{}}},\mathsf {t}_{})\) tokens in \(\mathsf{{m}_{}}\). When an enabled transition \(\mathsf {t}_{}\) is fired, it consumes \(\mathsf{{F}}(\mathsf{{p_{}}},\mathsf {t}_{})\) tokens from each \(\mathsf{{p_{}}}\), and produces \(\mathsf{{F}}(\mathsf {t}_{},\mathsf{{p'_{}}})\) tokens in each \(\mathsf{{p'_{}}}\). Formally, given \(x \in \mathsf{P}\cup \mathsf{Tr}\), we define the preset \({}^{\bullet }{x}\) and the postset \({x}{{}^{\bullet }}\) as multisets: \({}^{\bullet }{x}(y) = \mathsf{{F}}(y,x)\), and \({x}{{}^{\bullet }}(y) = \mathsf{{F}}(x,y)\). A transition \(\mathsf {t}_{}\) is enabled at \(\mathsf{{m}_{}}\) when \({}^{\bullet }{\mathsf {t}_{}} \subseteq \mathsf{{m}_{}}\). The transition relation between markings is defined as \(\mathsf{{m}_{}}\xrightarrow {\mathsf {t}_{}} \mathsf{{m}_{}}- {}^{\bullet }{\mathsf {t}_{}} + {\mathsf {t}_{}}{{}^{\bullet }}\), where \(\mathsf {t}_{}\) is enabled. We say that Open image in new window is a firing sequence from \(\mathsf{{m}_{}}\) to \(\mathsf{{m}'_{}}\) when Open image in new window, and in this case we say that \(\mathsf{{m}'_{}}\) is reachable from \(\mathsf{{m}_{}}\). We say that \(\mathsf{{m}'_{}}\) is reachable when it is reachable from \(\mathsf{{m}_{0}}\).

An occurrence net [8] is a Petri net such that: (i) \(|{\mathsf{{p_{}}}}{{}^{\bullet }}| \le 1\) for all \(\mathsf{{p_{}}}\); (ii) \(|{}^{\bullet }{\mathsf{{p_{}}}}| = 1\) if \(\mathsf{{p_{}}}\not \in \mathsf{{m}_{0}}\), and \(|{}^{\bullet }{\mathsf{{p_{}}}}| = 0\) if \(\mathsf{{p_{}}}\in \mathsf{{m}_{0}}\); (iii) \(\mathsf{{F}}\) is a relation, i.e. \(\mathsf{{F}}(x,y) \le 1\) for all xy; (iv) \(\mathsf{{F}}^*\) is a acyclic, i.e. \(\forall x,y \in \mathsf{P}\cup \mathsf{Tr}: (x,y) \in \mathsf{{F}}^* \wedge (y,x) \in \mathsf{{F}}^* \implies x=y\) (where \(\mathsf{{F}}^*\) is the reflexive and transitive closure of \(\mathsf{{F}}\)).

In Fig. 2 we transform a blockchain Open image in new window into a Petri net Open image in new window, where Open image in new window is an arbitrary relation between transactions. Although any relation Open image in new window ensures that Open image in new window is an occurrence net (Lemma 4 below), our main results hold when Open image in new window is a strong swappability relation. The transformation works as follows: the i-th transaction in Open image in new window is rendered as a transition Open image in new window, and transactions related by Open image in new window are transformed into concurrent transitions. Technically, this concurrency is specified as a relation < between transitions, such that Open image in new window whenever \(i < j\), but Open image in new window and Open image in new window are not related by Open image in new window. The places, the weight function, and the initial marking of Open image in new window are chosen to ensure that the firing ot transitions respects the relation <.
Fig. 2.

Construction of a Petri net from a blockchain Open image in new window.

Example 7

Consider the following transactions and functions of a contract Open image in new window:Let Open image in new window It is easy to check that these sets are safe approximations of their transactions (e.g., Open image in new window safely approximates the keys written by Open image in new window). By Definition 6 we have that Open image in new window, Open image in new window, but Open image in new window. We display Open image in new window in Fig. 3, where Open image in new window, Open image in new window, and Open image in new window. Note that Open image in new window can only be fired after Open image in new window, while Open image in new window can be fired independently from Open image in new window and Open image in new window. This is coherent with the fact that Open image in new window is swappable with both Open image in new window and Open image in new window, while Open image in new window and Open image in new window are not swappable. \(\diamond \)
Fig. 3.

Occurrence net for Example 7.

Step Firing Sequences. Theorem 5 below establishes a correspondence between concurrent and serial execution of transactions. Since the semantics of serial executions is given in terms of blockchain states \(\sigma _{}\), to formalise this correspondence we use the same semantics domain also for concurrent executions. This is obtained in two steps. First, we define concurrent executions of Open image in new window as the step firing sequences (i.e. finite sequences of sets of transitions) of Open image in new window. Then, we give a semantics to step firing sequences, in terms of blockchain states.

We denote finite sets of transitions, called steps, as \(\mathsf{U}_{},\mathsf{U'}_{},\ldots \). Their preset and postset are defined as \( \textstyle {}^{\bullet }{\mathsf{U}_{}} = \sum _{\mathsf{{p_{}}}\in \mathsf{U}_{}} {}^{\bullet }{\mathsf{{p_{}}}} \) and \( \textstyle {\mathsf{U}_{}}{{}^{\bullet }} = \sum _{\mathsf{{p_{}}}\in \mathsf{U}_{}} {\mathsf{{p_{}}}}{{}^{\bullet }} \), respectively. We say that \(\mathsf{U}_{}\) is enabled at \(\mathsf{{m}_{}}\) when \({}^{\bullet }{\mathsf{U}_{}} \le \mathsf{{m}_{}}\), and in this case firing \(\mathsf{U}_{}\) results in the move \(\mathsf{{m}_{}}\xrightarrow {\mathsf{U}_{}} \mathsf{{m}_{}}- {}^{\bullet }{\mathsf{U}_{}} + {\mathsf{U}_{}}{{}^{\bullet }}\). Let Open image in new window be a finite sequence of steps. We say that \(\varvec{\mathsf{U}_{}}\) is a step firing sequence from \(\mathsf{{m}_{}}\) to \(\mathsf{{m}'_{}}\) if Open image in new window, and in this case we write \(\mathsf{{m}_{}}\xrightarrow {\varvec{\mathsf{U}_{}}} \mathsf{{m}'_{}}\).

Concurrent Execution of Transactions. We now define how to execute transactions in parallel. The idea is to execute transactions in isolation, and then merge their changes, whenever they are mutually disjoint. The state updated resulting from the execution of a transaction are formalised as in Definition 1.

An update collector is a function Open image in new window that, given a state Open image in new window and a transaction Open image in new window, gives an update Open image in new window which maps (at least) the updated qualified keys to their new values. In practice, update collectors can be obtained by instrumenting the run-time environment of smart contracts, so to record the state changes resulting from the execution of transactions. We formalise update collectors abstracting from the implementation details of such an instrumentation:

Definition 8 (Update collector)

We say that a function Open image in new window is an update collector when Open image in new window, for all Open image in new window and Open image in new window. \(\diamond \)

There exists a natural ordering of collectors, which extends the ordering between state updates (i.e., set inclusion, when interpreting them as sets of substitutions): namely, Open image in new window holds when Open image in new window. The following lemma characterizes the least update collector w.r.t. this ordering.

Lemma 5 (Least update collector)

Let Open image in new window, where we define Open image in new window as Open image in new window. Then, Open image in new window is the least update collector. \(\diamond \)

The merge of two state updates is the union of the corresponding substitutions; to avoid collisions, we make the merge operator undefined when the domains of the two updates overlap.

Definition 9 (Merge of state updates)

Let \(\pi _{0}\), \(\pi _{1}\) be state updates. When \({\text {keys}}({\pi _{0}}) \cap {\text {keys}}({\pi _{1}}) = \emptyset \), we define \(\pi _{0} \oplus \pi _{1}\) as follows:

The merge operator enjoys the commutative monoidal laws, and can therefore be extended to (finite) sets of state updates.

We now associate step firing sequences with state updates. The semantics of a step Open image in new window in \(\sigma _{}\) is obtained by applying to \(\sigma _{}\) the merge of the updates Open image in new window, for all \(i \in 1..n\)—whenever the merge is defined. The semantics of a step firing sequence is then obtained by folding that of its steps.

Definition 10 (Semantics of step firing sequences)

We define the semantics of step firing sequences, given Open image in new window and Open image in new window, as:

Example 8

Let Open image in new window, and Open image in new window be as in Example 7, and let Open image in new window. Since Open image in new window, Open image in new window, and Open image in new window, we have:Note that, for all \(\sigma _{}\):So, the serial execution of Open image in new window and Open image in new window (in both orders) is equal to their concurrent execution (similarly for Open image in new window and Open image in new window). Instead, for all Open image in new window such that Open image in new window:So, concurrent executions of Open image in new window and Open image in new window may differ from serial ones. This is coherent with the fact that, in Fig. 3, Open image in new window and Open image in new window are not concurrent. \(\diamond \)

Concurrent Execution of Blockchains. Theorem 5 relates serial executions of transactions to concurrent ones (which are rendered as step firing sequences). Item (a) establishes a confluence property: if two step firing sequences lead to the same marking, then they also lead to the same blockchain state. Item (b) ensures that the blockchain, interpreted as a sequence of transitions, is a step firing sequence, and it is maximal (i.e., there is a bijection between the transactions in the blockchain and the transitions of the corresponding net). Finally, item (c) ensures that executing maximal step firing sequences is equivalent to executing serially the blockchain.

Theorem 5

Let Open image in new window. Then, in Open image in new window:
  1. (a)

    if \(\mathsf{{m}_{0}} \xrightarrow {\varvec{\mathsf{U}_{}}} \mathsf{{m}_{}}\) and \(\mathsf{{m}_{0}} \xrightarrow {\varvec{\mathsf{U'}_{}}} \mathsf{{m}_{}}\), then Open image in new window, for all reachable Open image in new window;

     
  2. (b)

    Open image in new window is a maximal step firing sequence;

     
  3. (c)

    for all maximal step firing sequences Open image in new window, for all reachable Open image in new window, Open image in new window.

     

Remarkably, the implications of Theorem 5 also apply to Open image in new window.

Example 9

Recall Open image in new window and Open image in new window from Example 7, let Open image in new window, and let Open image in new window be such that Open image in new window. As predicted by item (c) of Theorem 5:Let Open image in new window. We have that Open image in new window and Open image in new window lead to the same marking, where the places Open image in new window, Open image in new window and Open image in new window contain one token each, while the other places have no tokens. By item (a) of Theorem 5 we conclude that Open image in new window. Now, let Open image in new window. Note that, although \(\varvec{\mathsf{U''}_{}}\) is maximal, it is not a step firing sequence, since the second step is not enabled (actually, Open image in new window and Open image in new window are not concurrent, as pointed out in Example 8). Therefore, the items of Theorem 5 do not apply to \(\varvec{\mathsf{U''}_{}}\), coherently with the fact that \(\varvec{\mathsf{U''}_{}}\) does not represent any sequential execution of Open image in new window. \(\diamond \)

5 Case Study: ERC-721 Token

We now apply our theory to an archetypal Ethereum smart contract, which implements a “non-fungible token” following the standard ERC-721 interface [14, 15]. This contract defines the functions to transfer tokens between users, and to delegate their trade to other users. Currently, token transfers involve \(\sim \)50% of the transactions on the Ethereum blockchain [1], with larger peaks due to popular contracts like Cryptokitties [22].

We sketch below the implementation of the Token contract, using Solidity, the main high-level smart contract language in Ethereum (see Appendix B of [6] for the full implementation).

The contract state is defined by the following mappings:

Each token is uniquely identified by an integer value (of type uint256), while users are identified by an address. The mapping owner maps tokens to their owners’ addresses (the zero address is used to denote a dummy owner). The mapping exists tells whether a token has been created or not, while balance gives the number of tokens owned by each user. The mapping operatorApprovals allows a user to delegate the transfer of all her tokens to third parties.

The function transferFrom transfers a token from the owner to another user. The require assertion rules out some undesirable cases, e.g., if the token does not exist, or it is not owned by the from user, or the user attempts to transfer the token to himself. Once all these checks are passed, the transfer succeeds if the sender of the transaction owns the token, or if he has been delegated by the owner. The mappings owner and balance are updated as expected.
The function setApprovalForAll delegates the transfers of all the tokens of the sender to the operator when the boolean isApproved is true, otherwise it revokes the delegation.
Assume that user Open image in new window owns two tokens, identified by the integers 1 and 2, and consider the following transactions:We have that Open image in new window, Open image in new window, and Open image in new window (this can be proved e.g. by using the static approximations in Appendix B of [6]), while the other combinations are not swappable. Let Open image in new window. The resulting occurrence net is displayed in Fig. 4. For instance, let Open image in new window, i.e. Open image in new window and Open image in new window are executed concurrently, as well as Open image in new window and Open image in new window. From item (c) of Theorem 5 we have that this concurrent execution is equivalent to the serial one.
Although this example deals with the marginal case where the sender and the receiver of tokens overlap, in practice the large majority of transactions in a block either involves distinct users, or invokes distinct ERC-721 interfaces, making it possible to increase the degree of concurrency of transferFrom transactions.
Fig. 4.

Occurrence net for the blockchain Open image in new window of the ERC-721 token.

6 Related Work and Conclusions

We have proposed a static approach to improve the performance of blockchains by concurrently executing transactions. We have started by introducing a model of transactions and blockchains. We have defined two transactions to be swappable when inverting their order does not affect the blockchain state. We have then introduced a static approximation of swappability, based on a static analysis of the sets of keys read/written by transactions. We have rendered concurrent executions of a sequence of transactions as step firing sequences in the associated occurrence net. Our main technical result, Theorem 5, shows that these concurrent executions are semantically equivalent to the sequential one.

We can exploit our results in practice to improve the performances of miners and validators. Miners should perform the following steps to mine a block:
  1. 1.

    gather from the network a set of transactions, and put them in an arbitrary linear order Open image in new window, which is the mined block;

     
  2. 2.

    compute the relation Open image in new window on Open image in new window, using a static analysis of read/written keys;

     
  3. 3.

    construct the occurrence net Open image in new window;

     
  4. 4.

    execute transactions concurrently according to the occurrence net, exploiting the available parallelism.

     

The behaviour of validators is almost identical to that of miners, except that in step (1), rather than choosing the order of transactions, they should adhere to the ordering of the mined block Open image in new window. Note that in the last step, validators can execute any maximal step firing sequence which is coherent with their degree of parallelism: item (c) of Theorem 5 ensures that the resulting state is equal to the state obtained by the miner. The experiments in [12] suggest that parallelization may lead to a significant improvement of the performance of nodes: the benchmarks on a selection of representative contracts show an overall speedup of 1.33\(\times \) for miners and 1.69\(\times \) for validators, using only three cores.

Note that malevolent users could attempt a denial-of-service attack by publishing contracts which are hard to statically analyse, and therefore are not suitable for parallelization. This kind of attacks can be mitigated by adopting a mining strategy that gives higher priority to parallelizable transactions.

Applying Our Approach to Ethereum. Applying our theory to Ethereum would require a static analysis of read/written keys at the level of EVM bytecode. As far as we know, the only tool implementing such an analysis is ES-ETH [16]. However, the current version of the tool has several limitations, like e.g. the compile-time approximation of dictionary keys and of values shorter than 32 bytes, which make ES-ETH not directly usable to the purposes of our work. In general, precise static analyses at the level of the Ethereum bytecode are difficult to achieve, since the language has features like dynamic dispatching and pointer aliasing which are notoriously a source of imprecision for static analysis. However, coarser approximations of read/written keys may be enough to speed-up the execution of transactions. For instance, in Ethereum, blocks typically contain many transactions which transfer tokens between participants, and many of them involve distinct senders and receivers. A relatively simple analysis of the code of token contracts (which is usually similar to that in Sect. 5) may be enough to detect that these transactions are swappable.

Aiming at minimality, our model does not include the gas mechanism, which is used in Ethereum to pay miners for executing contracts. The sender of a transaction deposits into it some crypto-currency, to be paid to the miner which appends the transaction to the blockchain. Each instruction executed by the miner consumes part of this deposit; when the deposit reaches zero, the miner stops executing the transaction. At this point, all the effects of the transaction (except the payment to the miner) are rolled back. Our transaction model could be easily extended with a gas mechanism, by associating a cost to statements and recording the gas consumption in the environment. Remarkably, adding gas does not invalidate approximations of read/written keys which are correct while neglecting gas. However, a gas-aware analysis may be more precise of a gas-oblivious one: for instance, in the statement Open image in new window (where Open image in new window is a function which exceeds the available gas) a gas-aware analysis would be able to detect that x is not written.

Related Work. A few works study how to optimize the execution of smart contracts on Ethereum, using dynamic techniques adopted from software transactional memory [4, 12, 13]. These works are focussed on empirical aspects (e.g., measuring the speedup obtained on a given benchmark), while we focus on the theoretical counterpart. In [12, 13], miners execute a set of transactions speculatively in parallel, using abstract locks and inverse logs to dynamically discover conflicts and to recover from inconsistent states. The obtained execution is guaranteed to be equivalent to a serial execution of the same set of transactions. The work [4] proposes a conceptually similar technique, but based on optimistic software transactional memory. Since speculative execution is non-deterministic, in both approaches miners need to communicate the chosen schedule of transactions to validators, to allow them to correctly validate the block. This schedule must be embedded in the mined block: since Ethereum does not support this kind of block metadata, these approaches would require a “soft-fork” of the blockchain to be implemented in practice. Instead, our approach is compatible with the current Ethereum, since miners only need to append transactions to the blockchain. Compared to [4, 12], where conflicts are detected dynamically, our approach relies on a static analysis to detect potential conflicts. Since software transactional memory introduces a run-time overhead, in principle a static technique could allow for faster executions, at the price of a preprocessing phase. Saraph and Herlihy [20] study the effectiveness of speculatively executing smart contracts in Ethereum. They sample past blocks of transactions (from July 2016 to December 2017), replay them by using a speculative execution engine, and measure the speedup obtained by parallel execution. Their results show that simple speculative strategies yield non-trivial speed-ups. Further, they note that many of the data conflicts (i.e. concurrent read/write accesses to the same state location) arise in periods of high traffic, and they are caused by a small number of popular contracts, like e.g. tokens.

In the permissioned setting, Hyperledger Fabric [3] follows the “execute first and then order” paradigm: transactions are executed speculatively, and then their ordering is checked for correctness [2]. In this paradigm, appending a transaction requires a few steps. First, a client proposes a transaction to a set of “endorsing” peers, which simulate the transaction without updating the blockchain. The output of the simulation includes the state updates of the transaction execution, and the sets of read/written keys. These sets are then signed by the endorsing peers, and returned to the client, which submits them to the “ordering” peers. These nodes order transactions in blocks, and send them to the “committing” peers, which validate them. A block Open image in new window is valid when, if a key Open image in new window is read by transaction Open image in new window, then Open image in new window has not been written by a transaction Open image in new window with \(j<i\). Finally, validated blocks are appended to the blockchain. Our model is coherent with Ethereum, which does not support speculative execution.

Future Works. A relevant line of research is the design of domain-specific languages for smart contracts that are directly amenable to techniques that, like ours, increase the degree of concurrency of executions. For this purpose, the language should support static analyses of read/written keys, like the one we use to define the strong swappability relation. Although the literature describes various static analyses of smart contracts, most of them are focussed on finding security vulnerabilities, rather than enhancing concurrency.

Outside the realm of smart contracts, a few papers propose static analyses of read/written variables. The paper [11] describes an analysis based on separation logic, and applies it to resolve conflicts in the setting of snapshot isolation for transactional memory in Java. When a conflict is detected, the read/write sets are used to determine how the code can be modified to resolve it. The paper [10] presents a static analysis to infer read and write locations in a C-like language with atomic sections. The analysis is used to translate atomic sections into standard lock operations. The design of new smart contract languages could take advantage of these analyses.

Notes

Acknowledgements

Massimo Bartoletti is partially supported by Aut. Reg. Sardinia projects “Smart collaborative engineering” and “Sardcoin”. Letterio Galletta is partially supported by IMT Lucca project “PAI VeriOSS” and by MIUR project PRIN 2017FTXR7S “Methods and Tools for Trustworthy Smart Systems”. Maurizio Murgia is partially supported by MIUR PON “Distributed Ledgers for Secure Open Communities” and by Aut. Reg. Sardinia project “Smart collaborative engineering”.

References

  1. 1.
  2. 2.
  3. 3.
    Androulaki, E., et al.: Hyperledger fabric: a distributed operating system for permissioned blockchains. In: EuroSys, pp. 30:1–30:15 (2018).  https://doi.org/10.1145/3190508.3190538
  4. 4.
    Anjana, P.S., Kumari, S., Peri, S., Rathor, S., Somani, A.: An efficient framework for optimistic concurrent execution of smart contracts. In: PDP, pp. 83–92 (2019).  https://doi.org/10.1109/EMPDP.2019.8671637
  5. 5.
    Bartoletti, M., Galletta, L., Murgia, M.: A minimal core calculus for solidity contracts. In: Pérez-Solà, C., Navarro-Arribas, G., Biryukov, A., Garcia-Alfaro, J. (eds.) DPM/CBT -2019. LNCS, vol. 11737, pp. 233–243. Springer, Cham (2019).  https://doi.org/10.1007/978-3-030-31500-9_15CrossRefGoogle Scholar
  6. 6.
    Bartoletti, M., Galletta, L., Murgia, M.: A true concurrent model of smart contracts executions. CoRR abs/1905.04366 (2020). http://arxiv.org/abs/1905.04366
  7. 7.
    Bernstein, A.J.: Analysis of programs for parallel processing. IEEE Trans. Electron. Comput. EC-15(5), 757–763 (1966).  https://doi.org/10.1109/PGEC.1966.264565
  8. 8.
    Best, E., Devillers, R.R.: Sequential and concurrent behaviour in Petri net theory. Theor. Comput. Sci. 55(1), 87–136 (1987).  https://doi.org/10.1016/0304-3975(87)90090-9MathSciNetCrossRefzbMATHGoogle Scholar
  9. 9.
    Buterin, V.: Ethereum: a next generation smart contract and decentralized application platform (2013). https://github.com/ethereum/wiki/wiki/White-Paper
  10. 10.
    Cherem, S., Chilimbi, T.M., Gulwani, S.: Inferring locks for atomic sections. In: ACM SIGPLAN PLDI, pp. 304–315 (2008).  https://doi.org/10.1145/1375581.1375619
  11. 11.
    Dias, R.J., Lourenço, J.M., Preguiça, N.M.: Efficient and correct transactional memory programs combining snapshot isolation and static analysis. In: USENIX Conference on Hot Topics in Parallelism (HotPar) (2011)Google Scholar
  12. 12.
    Dickerson, T.D., Gazzillo, P., Herlihy, M., Koskinen, E.: Adding concurrency to smart contracts. In: ACM PODC, pp. 303–312 (2017).  https://doi.org/10.1145/3087801.3087835
  13. 13.
    Dickerson, T., Gazzillo, P., Herlihy, M., Koskinen, E.: Adding concurrency to smart contracts. Distrib. Comput. 33, 209–225 (2020).  https://doi.org/10.1007/s00446-019-00357-zMathSciNetCrossRefGoogle Scholar
  14. 14.
    Entriken, W., Shirley, D., Evans, J., Sachs, N.: EIP 721: ERC-721 non-fungible token standard. https://eips.ethereum.org/EIPS/eip-721
  15. 15.
    Fröwis, M., Fuchs, A., Böhme, R.: Detecting token systems on ethereum. In: Goldberg, I., Moore, T. (eds.) FC 2019. LNCS, vol. 11598, pp. 93–112. Springer, Cham (2019).  https://doi.org/10.1007/978-3-030-32101-7_7CrossRefGoogle Scholar
  16. 16.
    Marcia, D.: ES-ETH: ethereum state change examiner (2019). https://github.com/DiegoMarcia/ES-ETH
  17. 17.
    Mazurkiewicz, A.: Basic notions of trace theory. In: de Bakker, J.W., de Roever, W.-P., Rozenberg, G. (eds.) REX 1988. LNCS, vol. 354, pp. 285–363. Springer, Heidelberg (1989).  https://doi.org/10.1007/BFb0013025CrossRefGoogle Scholar
  18. 18.
    Nielson, F., Nielson, H.R., Hankin, C.: Principles of Program Analysis (1999).  https://doi.org/10.1007/978-3-662-03811-6CrossRefGoogle Scholar
  19. 19.
    Reisig, W.: Petri Nets: An Introduction. Monographs in Theoretical Computer Science: An EATCS Series, vol. 4. Springer, Heidelberg (1985).  https://doi.org/10.1007/978-3-642-69968-9CrossRefzbMATHGoogle Scholar
  20. 20.
    Saraph, V., Herlihy, M.: An empirical study of speculative concurrency in Ethereum smart contracts. CoRR abs/1901.01376 (2019). http://arxiv.org/abs/1901.01376
  21. 21.
    Szabo, N.: Formalizing and securing relationships on public networks. First Monday 2(9) (1997). http://firstmonday.org/htbin/cgiwrap/bin/ojs/index.php/fm/article/view/548
  22. 22.
    Young, J.: CryptoKitties sales hit \$12 million, could be Ethereum’s killer app after all (2017). https://cointelegraph.com/news/cryptokitties-sales-hit-12-million-could-be-ethereums-killer-app-after-all

Copyright information

© IFIP International Federation for Information Processing 2020

Authors and Affiliations

  1. 1.University of CagliariCagliariItaly
  2. 2.IMT School for Advanced StudiesLuccaItaly
  3. 3.University of TrentoTrentoItaly

Personalised recommendations