========================= |langname| in a nutshell ========================= .. highlight:: btm BALZaC (for Bitcoin Abstract Language, Analyzer and Compiler) is a domain-specific language to write Bitcoin transactions, based on the paper [AB+18FC]_. |langname| features a simple syntax to express Bitcoin transactions. We illustrate it through a series of examples, that you can experiment with in the `online editor `_. .. _label_t_modeling: """"""""""""""""""""" A basic transaction """"""""""""""""""""" Bitcoin transactions transfer currency, the *bitcoins* (BTC). Each transaction has one or more inputs, from where it takes the bitcoins, and one or more outputs, which specify the recipient(s). |langname| also allows for transactions with no inputs: even though these transactions cannot be appended *as is* to the actual Bitcoin blockchain, they are useful to refer to transactions which are not known at specification time. An example of transaction with no inputs is the following: .. code-block:: balzac transaction T { input = _ // no input output = 50 BTC: fun(x) . x == 42 } The output field of transaction ``T`` contains a value, :balzac:`50 BTC`, and an *output script*, :balzac:`fun(x) . x==42`. This means that 50 bitcoins will be transferred to any transaction which provides a *witness* ``x`` such that :balzac:`x == 42`. To append ``T`` to the Bitcoin blockchain, the placeholder ``_`` for the input must be replaced with the identifier of an unspent transaction already on the blockchain, which has at least 50 BTC. You can use the `web editor `_ to write |langname| transactions, to check their syntax, and to compile them into actual Bitcoin transactions. The output of the compiler is a serialized transaction for the Bitcoin test network (testnet). To generate transactions for the main network (mainnet), one must specify the network as follows: .. code-block:: balzac network mainnet // default is testnet For instance, let us paste transaction ``T`` into the editor and add command :balzac:`eval T` to it. Now, if we hit the button *Evaluate*, the web editor shows in the output box the transaction ``T`` in Bitcoin (testnet) serialization format. .. figure:: _static/img/compiling_t.png :scale: 75 % :class: img-border :align: center The serialized transaction can be sent to the Bitcoin network using the Bitcoin client command ``bitcoin-cli sendrawtransaction``. However, in order to be published, ``T`` must redeem a real transaction on the blockchain. In |langname|, it is possible to define a transaction using its hex format, for example: .. code-block:: balzac const realT = tx:0000fa00120... // Hex of a real transaction transaction T { input = realT: ... // witness to redeem realT output = 50 BTC: fun(x) . x == 42 } .. _label_transaction_redeeming: """"""""""""""""""""""""""""""" Redeeming a transaction """"""""""""""""""""""""""""""" If one needs to use the bitcoin stored within ``T``, she can redeem it with the following transaction: .. code-block:: balzac transaction T1 { input = T: 42 output = 50 BTC: fun(x). x != 0 // any constraint chosen by the user } Transaction ``T1`` redeems ``T`` by indicating it in the :balzac:`input` field, and by providing the number 42 as *witness*. The value 42 is the actual parameter which replaces the formal parameter ``x`` in the output script :balzac:`fun(x) . x == 42`, and makes the script evaluate to true. Any other witness would make the script evaluate to false, and would prevent the transaction ``T1`` from being added to the blockchain. A transaction cannot be spent twice: hence, once ``T1`` is on the blockchain, no other transaction having ``T`` as input can be appended. Note that ``T1`` is redeeming exactly the :balzac:`50 BTC` deposited in ``T``: in practice, to be able to append ``T1`` to the blockchain, the value in output of a transaction must be strictly less than the value in input. The difference is retained by Bitcoin miners as a fee for their work, and currently, transactions with zero fee are not likely to be added to the blockchain. Now, let us insert both ``T`` and ``T1`` in the editor. While we write, the editor performs some static checks and signals the errors. For instance, if instead of the value ``42`` we provide another witness for ``T`` (say for instance value ``4``), the editor will display a warning. If the input field of ``T1`` has a wrong reference (say ``T3``), or if the total amount of outgoing bitcoins is greater than the incoming one, the editor will signal the error. .. _label_t_signature_modeling: """"""""""""""""""""""""""""""" Signature verification """"""""""""""""""""""""""""""" The output scripts of ``T`` and ``T1`` are naïve, since anyone can produce the right witnesses. Usually, one wants to transfer bitcoins to a specific user. For instance, the following transaction ``T2`` makes the 50 BTC of ``T1`` redeemable only by user Alice: .. code-block:: balzac // Alice's public key const pubA = pubkey:03d0272bb640bdbbcaedce10ef69ad6d9d8c7b9c61ff2aa4cf4ed27865d287c224 transaction T2 { input = T1: 12 output = 50 BTC: fun(x) . versig(pubA; x) } The constant ``pubA`` declares Alice's *public key*. Users can generate as many public keys as they want. The :ref:`predicate ` :balzac:`versig(pubA; x)` in the output script of ``T2`` is true if ``x`` is a valid signature of the transaction which redeems ``T2``, computed with Alice's private key. The transaction ``T2`` can be redeemed by a transaction ``T3`` made as follows: .. code-block:: balzac // Alice's private key const kA = key:cVdDtCe2Gb6HWeCEzRTpZEitgxYonPtvLfGZrpprWV6BTJ3N37Lw transaction T3 { input = T2: sig(kA) output = 50 BTC: fun(x) . versig(pubA; x) // any condition chosen by Alice } The witness :balzac:`sig(kA)` is the :ref:`signature ` of transaction ``T3`` (without considering the witness itself) using the private key ``kA``. You can use the online form on the sidebar to generate new addresses and keys. .. figure:: _static/img/sidebar.png :scale: 70% :class: img-border :align: center .. _label_t1_modeling: """"""""""""""""""""""""""""""" Multiple inputs and outputs """"""""""""""""""""""""""""""" Transactions can have more than one output, in order to split the money on different recipients. For instance, the amount of bitcoins in ``T4`` is split in two parts: .. code-block:: balzac // Bob's other public key const pubB = pubkey:0289654c430032f20f8464a84a1f9b3289ceaff8d6cd93c9b654e59a8c5a1cc1b0 transaction T4 { input = T3:sig(kA) output = [ 40 BTC: fun(x) . versig(pubA; x); 10 BTC: fun(x) . versig(pubB; x) ] } In this transaction, the output field has two items, that can be redeemed separately. Transactions can have more than one input, in case they need to gather money from several sources. For each input, the transaction must provide a suitable witness. In case inputs refer to a transaction with multiple outputs, their outputs are numbered starting from 0. For instance: .. code-block:: balzac // Bob's private key const kB = key:cVifQzXqqQ86udHggaDMz4Uq66Z7RGXJo5PdVjzRP12H1NDCFsLV transaction T5 { input = [ T4@0: sig(kA); T4@1: sig(kB) ] output = 50 BTC: fun(x) . versig(pubA; x) } which calculates the signature of transaction ``T5`` using the private key ``k``. (see :ref:`function list ` ). """"""""""""""""""""""" Parametric transactions """"""""""""""""""""""" Transaction definition can be parametric. For instance, in the following example ``T6`` takes one parameter of type :balzac:`pubkey` and uses it in the output script. .. code-block:: balzac // parametric transaction transaction T6(pub) { input = _ output = 1BTC: fun(x). versig(pub;x) } To be able to evaluate ``T6``, one must instantiate that one parameter, like: .. code-block:: balzac eval T6(pubA) One can also use T6 in the definition of its redeeming transaction, as follows: .. code-block:: balzac transaction T7 { input = T6(pubA): sig(kA) output = 1BTC: fun(x). versig(pubB;x) } In case the parameter is a witness, it can be left unspecified as long as it is needed, using the symbol ``_``. For instance, transaction ``T9`` is obtained by ``T8``, without providing a witness : .. code-block:: balzac transaction T8(s:signature, n:int) { input = T7: s output = 1BTC: fun(x, m). versig(pubA;x) && m == sha256( n ) } //transaction with empty signature const T9 = T8(_, 4) The generation of a signature inside a transaction is done at compilation time, so that all the parameters have been instantiated. Indeed: .. code-block:: balzac transaction T8_bis(n:int) { input = T7: sig(kB) output = 1BTC: fun(x, m). versig(pubB;x) && m == sha256( n ) } eval T9_bis(4) //sig(kA) is calculated now """""""""""" Participants """""""""""" |langname| supports the definition of *participants*. Participants can be declared as :balzac:`participant Alice {...}` and enclose constant and transaction declarations. Consider the following example: .. code-block:: balzac // Global declarations const pubA = pubkey:0364de313bd23bca4ed8db326dc3c66c32a6aa3687ef6b885445c226b9e2366ebf const fee = 0.0003 BTC participant Alice { // Local declarations const name = "Alice" transaction T { input = _ output = 1 BTC - fee : fun(x, y) . x == name && versig(pubA; y) } } eval pubA, Alice.T The snippet above defines two global declarations ``pubA`` and ``fee``, that are globally visible within the same file. *Local declarations* can be defined within participants. In order to refers to the participant declarations, the participant name must precede the declaration name, e.g. ``Alice.T`` or ``Alice.name``. *Private local declarations* are preceded by the keyword :balzac:`private`: a private declaration is visible only within the participant in which is declared. In the following example the constant ``kA`` is not visible outside the Alice's participant. .. code-block:: balzac :emphasize-lines: 8 participant Alice { private const pubA = pubkey:0364de313bd23bca4ed8db326dc3c66c32a6aa3687ef6b885445c226b9e2366ebf } transaction T { input = _ output = 10 BTC : fun(x) . versig(Alice.pubA; x) // Error: couldn't resolve 'Alice.kA' }