tinybook module
Minimal pure-Python library that demonstrates a basic workflow for an encrypted order book by leveraging a secure multi-party computation (MPC) protocol.
- class tinybook.tinybook.node[source]
Bases:
object
Data structure for maintaining the information associated with a node and performing node operations.
Suppose that a workflow is supported by three parties. The
node
objects would be instantiated locally by each of these three parties.>>> nodes = [node(), node(), node()]
The preprocessing workflow that the nodes must execute can be simulated using the
preprocess
function. It is assumed that all permitted prices are integers greater than or equal to0
and strictly less than a fixed maximum value. The number of distinct prices must be supplied to thepreprocess
function.>>> preprocess(nodes, prices=16)
A request must be submitted for the opportunity to submit an order. The clients can create
request
instances for this purpose. Below, two clients each create their request.>>> request_ask = request.ask() >>> request_bid = request.bid()
Each client can deliver their request to each node, and each node can then locally use its
masks
method to generate masks that can be returned to the requesting client.>>> masks_ask = [node.masks(request_ask) for node in nodes] >>> masks_bid = [node.masks(request_bid) for node in nodes]
Each client can then generate locally an
order
instance (i.e., a masked representation of the order).>>> order_ask = order(masks_ask, 4) >>> order_bid = order(masks_bid, 9)
Each client can broadcast its masked order to all the nodes. Each node can locally assemble these as they arrive. Once a node has received both masked orders, it can determine its shares of the overall outcome using the
outcome
method.>>> shares = [node.outcome(order_ask, order_bid) for node in nodes]
The overall outcome can be reconstructed from the shares by the workflow operator using the
reveal
function. The outcome is eitherNone
(if the bid price does not equal or exceed the ask price) or arange
instance representing the bid-ask spread (where for arange
instancer
, the ask price ismin(r)
and the bid price ismax(r)
).>>> reveal(shares) range(4, 10) >>> min(reveal(shares)) 4 >>> max(reveal(shares)) 9
In the example below, the bid price does not exceed the price of the ask.
>>> order_ask = order(masks_ask, 11) >>> order_bid = order(masks_bid, 7) >>> shares = [node.outcome(order_ask, order_bid) for node in nodes] >>> reveal(shares) is None True
- class tinybook.tinybook.request[source]
-
Data structure for representing a request to submit an order. A request can be submitted to each node to obtain corresponding masks for an order.
Instances should only be constructed using the
request.ask
andrequest.bid
methods.
- class tinybook.tinybook.order(masks, price)[source]
Bases:
list
Data structure for representing an order that can be broadcast to nodes.
- Parameters
Suppose masks have already been obtained from the nodes via the steps below.
>>> nodes = [node(), node(), node()] >>> preprocess(nodes, prices=16) >>> price = 7 >>> masks = [node.masks(request.ask()) for node in nodes]
This method can be used to mask the order (in preparation for broadcasting it to the nodes).
>>> isinstance(order(masks, price), order) True
- tinybook.tinybook.preprocess(nodes, prices)[source]
Simulate a preprocessing workflow among the supplied nodes for a workflow that supports the specified number of distinct prices (where prices are assumed to be integers greater than or equal to
0
and strictly less than the valueprices
).- Parameters
The example below performs a preprocessing workflow involving three nodes.
>>> nodes = [node(), node(), node()] >>> preprocess(nodes, prices=16)
- tinybook.tinybook.reveal(shares)[source]
Reconstruct the overall workflow outcome (representing the bid-ask spread) from the shares obtained from each node.
- Parameters
shares (
List
[List
[modulo
]]) – Shares of overall outcome (where each share is a list in which each entry corresponds to one of the permitted price values).
Suppose the shares below are returned from the three nodes in a workflow.
>>> from modulo import modulo >>> p = 340282366920938463463374607431768196007 >>> shares = [ ... [ ... modulo(191698724691236883130020433754311906556, p), ... modulo(192553930942215974753329735796719934503, p), ... modulo(96579911660242665783999103846211668558, p) ... ], ... [ ... modulo(203604595735418244883008588068488824844, p), ... modulo(213569286850324010515175569194586924260, p), ... modulo(97156260151248494516609766219626086128, p) ... ], ... [ ... modulo(285261413415221798913720193040735660613, p), ... modulo(274441516049336941658243909872229533251, p), ... modulo(146546195109447303162765737365930441321, p) ... ] ... ]
This method combines such shares into an overall workflow outcome by reconstructing the individual components and extracting the bid-ask spread (if possible). In particular, the output is either
None
(if the bid price does not equal or exceed the ask price) or arange
instance representing the bid-ask spread (where for arange
instancer
, the ask price ismin(r)
and the bid price ismax(r)
).>>> reveal(shares) range(1, 3)