Skip to main content

Alphabill Predicate Playground

To get yourself familiarized with how Alphabill transactions, predicates, and unlock scripts work, first go to the Predicate Playground. The playground provides three main areas for you to work with: coding interface, list of bills, and keychain.

  • Coding interface: used for entering unlock scripts, predicates, sign and submit transactions for bills.

    Coding Area

  • List of bills: includes bills you can work with in the playground. You can create more bills or delete existing ones. Each bill has a unique identifier.

    Bill List

  • Keychain: includes keys you can use in the scripts to create and check signatures. Like in the list of bills, you can create more key pairs or delete existing ones.

    Keychain

You can delete a bill or a key pair by clicking the red x in the top right corner of the bill's or key pair's entry. If you want more bills or key pairs to work with, click the blue + in the top right corner. To reset the playground to the initial default state, refresh your browser.

First Transaction and Basic Concepts

When you first load the playground, a few default bills are present for you to work with. Scroll down to the bill list, and take a look at demo_bill1. Like shown in the figure below, the bill has an empty predicate.

"demo_bill1" Defaults

This means that the puzzle is really easy to solve: without defining the predicate, anyone can spend the bill at any time. All we need to do is push true onto the stack during the execution of the unlock script, and then the empty predicate will evaluate.

Since the predicate is empty, there are no operations, and so the resulting stack contains only the true value put there during the execution of the unlock script. And since this is the success condition for spending a bill, the transaction succeeds.

Example 1

  1. Unlock Script:

    push true
  2. New Predicate: leave empty

  3. After you click Execute, a message of a successful transaction is displayed.

While the transaction succeeded, it didn't do anything useful. We made a successful transaction with the bill, but because the Bearer Predicate field was empty, the same empty predicate remained on the bill.

Example 2

Let's see next what happens when things go wrong. While the previous example is the simplest possible way to spend this bill, it's not the only one. In fact, there are an infinite number of solutions.

  1. Unlock Script:

    push true
    dup
  2. New Predicate: leave empty

  3. After you click Execute, a message of a failed transaction is displayed. The playground shows a debugging message to help you understand why things have failed.

    Multiple Elements Error

The transaction failed, because while the top element of the stack is true, it is not the only element in the stack.

Example 3

Try this unlock script next.

  1. Unlock Script:

    push 42
    push 42
    ; push two equal ints onto the stack

    equal
    ; check that they are equal, which consumes them both and pushes true onto the stack
  2. New Predicate: leave empty

  3. After you click Execute, the transaction succeeds, but it didn't do anything interesting.

Second Transaction: Burning bills

This transaction shows what happens when you configure the bill with a new predicate.

Enter the following values into the Unlock Script and New Predicate fields:

  1. Unlock Script:

    push true
  2. New Predicate:

    push false
  3. After you click Execute, this transaction will also succeed.

But what did we do? We created a predicate that can never be spent by anyone ever again. This is because there are no possible sequence of operations that can be put into an unlock script that will solve this puzzle. No matter what comes before, at the very last step of execution, false will always be pushed onto the stack.

This is one way to "burn" a bill. It might seem like a waste, but there are applications where proof of burn can be useful.

Since this bill cannot be spent, we can no longer interact with it. You can delete the bill by clicking the red x in the top right corner of the bill's entry in the bill list.

Important

Before moving on to the third transaction, refresh the browser to reset the playground to the initial default state!

Third Transaction: Using keys

Let's do something more interesting. Use the same demo_bill1 as in the second transaction, but pay the bill to a public key you have access to in the Keychain.

By default, the Keychain includes two public keys simulating two users: one called $alice and another called $bob.

But what should the new predicate do? One common use case is when I want to pay to a particular person who has the private key portion of a particular asymmetric key pair, where the public key is one I know is associated with their identity. I want to make it so that only they can spend it. After I pay this way, the new owner can use their private key to make a digital signature, and spend the bill again.

  1. Unlock Script:

    push true
  2. New Predicate: try to create a predicate that only Alice can spend. The simplest way of writing this predicate is like this:

    ; We expect the stack to contain only a signature on the transaction itself.

    ; Push the public key of the new owner
    push $alice.publicKey

    ; Use and consume the public key value (topmost element) to verify and
    ; consume the signature (second element on the stack) on the transaction.
    ; Pushes the boolean result back to the stack making it the only remaining value.
    check_signature
  3. Use Key: select alice key from the drop-down menu, and click Sign and then Execute.

  4. After this transaction is successful, you can scroll down to the bill list to inspect the state of demo_bill1. You should see the bill including something like the following in the Bearer Predicate field:

    This is the same predicate, but with the information related to the key variable $alice expanded to the full syntax, including type and encoding keywords, as well as with the actual hex value of Alice's public key.

Important

Next example uses the same bill for a new transaction, so do not refresh the browser!

Fourth Transaction: "Pay to public key hash"

For this transaction, transfer the same bill, but now from alice to bob. Let's use a different kind of predicate, called "pay to public key hash".

Depending on the kind of asymmetric key pair you are using, this might result in shorter predicates, since the hash of the public key is shorter than the public key itself. Doing things this way uses less space.

  1. Unlock Script: since there is no longer an empty predicate, you can't continue to use push true anymore; therefore, create and push a signature generated with the $alice key.

    push $signature

    This syntax will push a signature, but what signature? You need to create a signature before you can submit the transaction.

  2. New Predicate: this predicate is a more complicated than previous ones, but the comments in the script explain what is going on.

    ; We expect the stack to contain two elements:
    ; public key value (the topmost element)
    ; transaction signature (the second element)

    ; Duplicate the topmost element (the public key value)
    dup

    ; Calculate the hash value of the top element, and replace
    ; the topmost element with the calculated digest.
    hash "sha256"

    ; Push a constant hash value of the intended receivers
    ; public key to the stack.
    push $bob.sha256

    ; Compare and replace the two topmost hash values with
    ; a boolean value (true if they are equal, false otherwise)
    equal

    ; Fail execution if the topmost element is false
    verify

    ; At this point the stack is the same as in the
    ; beginning of the predicate.

    ; Use and consume the public key value (topmost element)
    ; to verify and consume the signature (second element on the
    ; stack) on the transaction. Pushes the boolean result
    ; back to the stack making it the only remaining value.
    check_signature
  3. Use Key:

    • Select the alice key from the Use Key drop-down menu, and click Sign.
    • You will see a hex encoded signature now present in the Transaction Signature text field. The $signature variable refers to this signature.

Important

For the fifth transaction, do not refresh the browser!

Fifth Transaction: More complex unlock scripts

Finally, burn the bill you have been working with. Before doing so, you need to solve the predicate created in the forth transaction above.

  1. Unlock Script: this time, the unlock script will be more complicated.

    push $signature

    ; Push the public key to the stack.
    ; The hash is computed by the bearer predicate.
    push $bob.publicKey

    As in the previous transaction, you need to prepare a signature to use.

  2. New Predicate: leave empty

  3. Use Key: select the bob key from the Use Key drop-down menu, since now the Bob's key controls this bill.

  4. Click Sign.

Summary

Congratulations, you have completed the Alphabill Predicate Playground walkthrough! To explore more use cases, see Example Use Cases and Predicates. Some were used in this walkthrough, but there are also others that demonstrate more advanced features of the Alphabill scripting language. We will add more use cases from time to time, as additional capabilities become available.