CodeNewbie Community 🌱

Ecaterina Teodoroiu
Ecaterina Teodoroiu

Posted on

Blockchain Development tutorial - How to start developing for MultiversX with Python

In this article I’m going to have a quick lesson on interacting with the Multiverse X blockchain
• We will learn to talk to the network through a so-called Network provider (proxy)
• than and we will create sign and broadcast transactions 
• query account State and storage 
• and also approach a few concepts of chronology and sharding 
… and we'll do all this by following two simple tutorials:

  1. Creating a simple passwords manager
  2. Interacting with a deep-history squad

The first one we'll create a simple minimalistic passwords manager with encrypted passwords and usernames stored in blockchain and secondly we'll query account state from a so-called deep history observing Squad but before diving into the tutorials let us meet erdpy (primary, monolithic, swiss-knife and erdpy-eggs (experimental, modularized > erdpy vNext) is the main tool and library that Python programmers use to develop on Multiverse X
However currently we are experimenting with a new set of libraries which we nicknamed erdpy-eggs and at some point into the future these libraries might replace large chunks of erdpy functionality and now we are gonna use erdpy X for the tutorials.

Tutorial 1: Passwords manager on the blockchain

• encrypt secret entries [usernames + passwords] using pynacl 
• store passwords on account storage [gas cost]
• call built-in function [SaveKeyValue]
• query and decrypt [no cost]

Our password manager will present itself as a simple [CLI] and it would be able to initialize a Multiverse X wallet and and a secret key that will be used to encrypt the secret entries the user names and the passwords. Of course it will be able to create retrieve update and delete those secret entries and the [CLI] will be extremely simple.
We'll define one argument sub parser for each flow that is will have a parser for the need flow one for the insert and update flow and another parser for the retrieve entries flow.

define one argument sub parser

Passwords manager / theory / account storage and SaveKeyValue

Multiverse X offers the possibility of storing arbitrary data into an account storage by calling SaveKeyValue which is the building function what is the built-in function. It's a function that doesn't belong to a Smart contract and you can think of it as a function that lives in the global namespace of the network like a global function and this is how a transaction that holds an invocation of self key value would look like and we're going to code such a transaction in our passwords manager.

Save Key Value Transaction

Here's an example of a Json dump from the account storage as retrieved from the API key and values now about encrypting the secret entries the usernames and the passwords in our application we'll use the secret that's separate from the Multiverse X wallet just that's for simplicity because we don't want to dive deep into cryptography right now in this tutorial (if you are interested here are more informations about this topic...).

We are going to use the pynacl secret box facility to encrypt and decrypt the data. 

Now let's see the init flow of the application

Here we create a Multiverse X wallet and for simplicity again we're going to use a wallet in the plain pen format which isn't actually recommended in real world applications.

Than here regenerate the secret used to encrypt and decrypt the usernames and the passwords. Now let's see the update and insert flow the upset flow here we ask the user to input usernames and passwords …and here we have them converted to give their key value pairs encrypted to encrypted key value pairs and here we create and also sign a transaction that invokes the aforementioned safety valuability function.

Passwords manager / Secret entry

We'll shortly see how this function is defined in a few moments but before that let's have a look at the secret entry class. How is it defined in our application?
Here is the encryption part and here would be the conversion of the instance to an account key value pair.

Today we have a question coming in: how expensive is storing data with save key value? Is it very expensive or more like storage chain are expensive etc.

Filecoin are very well. This kind of function went is it invoked it doesn't trigger an execution in the actual VM because the function is actually implemented natively into the node, into the protocol. It doesn't execute a smart contract actually. It's some kind of a global function of the protocol.
So um even though even it doesn't execute in the VM it still increases a small cost a small gas cost and I think we will see later how much gas is it required call save key value and of course a very little amount of gas will be needed to save one entry. 
If you save more entries the cost will grow a little bit but still be sufficiently small. If it answers the questions I would say the costs are very-very low. 
We implement the extraction part, we extract the secret entries from a set of key value pairs that are fetched from the account storage.

Passwords manager / Secret entry

Here will be the decryption part and this would be the code that creates a transaction that invokes save key value, the safety value building function. 
We are preparing the transaction like acquiring the chain ID, acquiring the account loans. We compute the gas limit. 

Password manager / Create transaction

We won't see the code that computes the guest limit here but we'll see the output value as an example and here we signed a transaction.
That's the value of the guest limit and it would be multiplied with a gas fee and that would result into the actual cost that will be taken by the network.
So this is how a prepared transaction looks like and it's ready to be broadcasted.

Password manager / transaction

If we were to run the upsert flow of our application we will see something like this.

Passwords manager / run

It's a simple application so we wouldn't expect the another kind of user interface.

Let's go to retrieving the secret entries, the retrogen flow.
Here we fetch all the pairs from the account storage and we search for the entries that we've created before and decrypt them. 

Passwords manager / retrieve entries

If you were to run this retrieve flow would get a previously saved username and password.

Passwords manager / run

Yep! That that was the first tutorial and now we've reached the second one.

Tutorial 2: Interacting with a deep-history squad

We will consume data from a so-called deep history observing squad and a deep history of serving squad is basically a set of network observers of nodes that retain um not pruned history of the blockchain and allows one to query the state of an account at an arbitrary Block in the past.
Now in this tutorial we will sketch a simple HTTP API using bottle um an API which allows one to inspect the state of an account at a given timestamp and we'll have to implement the mapping from a timestamp to a to a block index our application will consist of bottle controllers and an underlying custom network provider which would be able to fetch balances for both native and custom currencies and also to fetch whole account storage data like the one we've used in the first tutorial actually.

All queries will be performed by timestamp that's what we want and those bottle controllers would be able to resolve these kinds of HTTP get requests like getting balances, getting account data and here is a small sketch of how would that endpoints look in the code.

Now we are going to see how could we extend the default Network provider to implement what we want. Let's have the example of getting the native balance of an account which is the EGLD balance at a given timestamp which in the end needs to be converted actually to block nodes.

Deep-history app / network provider client

So the most important thing here is to implement get block by time and how would we Implement get block by time and why would we also need to take into consideration the address of interest while doing so well.

Deep-history app / get_block_by_time

Let's talk a bit about rounds and blocks and then a bit about sharding.

The Multiverse X magnet was born back in July 2020 and back then it was all around the network and since then at each six seconds at each round the blockchain produces blocks and generally speaking it produces one block per round per shard and since the given the Genesis time and given the duration of a round it's easy to compute a round index for any given timestamp.

Deep-history app / theory / rounds and blocks

So back to our function git block by time we can easily get the round but then the network has currently three shards and plus a special Shard called the metal chain anyway all accounts belong to one of these shards with respect to a partitioning rule.
That's again outside the scope of this tutorial and every Shard builds what can be seen as an individual blockchain in a way and every shard produces one block per round one at each six seconds though if you were to go now and sample network data we would see that block numbers do not match round numbers.

They do differ and this is because in some work rare cases there are rounds when shard blocks aren't produced. 
This is what we call an imperfect hit rate.

Deep-history app / theory / sharding

Deep-history app / theory / sharding

Deep-history app / theory / sharding

Now let's go back to our get block by time. We really do need a way to get the block index by round index. How do we do that? we'll do so by calling a special API endpoint which is able to map I need a round index to a set of Shard blocks that were produced in that round therefore here's our working implementation of get block by time.

Deep-history app / get_block_by_time

Deep-history app / theory / blocks by round

And this implementation also handles some worst case scenarios with rounds that don't produce any blocks.

Let's go back to our custom network provider and in addition to getting native balances let's instruct it to also fetch a custom balances which we call ESDT balances.

Deep-history app / get_block_by_time

Also let's instruct it to fetch whole account data in a similar fashion like getting native balances. 

Deep-history app / network provider client

Now we should be ready to query account data and balances at any given timestamp in the past. Here on the screen you can see a minimalistic dashboard and on this dashboard you can interact with the newly created portals API.

Deep-history app / run (with dashboard)


What have we done:

  • tutorial: creating a simple passwords manager.
  • tutorial: interacting with a deep-history squad

What have we learned:

  • interact with a network provider (proxy)
  • create and broadcast,transactions
  • query account state
  • handle chronology and sharding

thank You,
have fun building!

Top comments (0)