I am happy to start July announcing the third version of MAIA, which comes with 3 changes: i) fields, ii) views and iii) trees.
Fields
From now on MAIA addresses are flexible and they can index multiple fields. How does this work?
MAIA 2 defined two methods, POST and GET. The interaction was as follows:
>>> POST(seed: x, address: y)
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< y
>>> POST(seed: x, address: y')
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< y'
MAIA 3 defines the same methods, although it changes the format of the call (in the POST method) and the format of the result (in the GET method). Now the iteration is as follows:
>>> POST(seed: x, data: {address: y, twitter: t})
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< {address: y, twitter: t}
Note that the fields of the channel are updated individually, performing a merge with the previous values, which allows adding, modifying or deleting fields in a simple way.
>>> // New field
>>> POST(seed: x, data: {facebook: f})
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< {address: y, twitter: t, facebook: f}
>>> // Modify field
>>> POST(seed: x, data: {facebook: f'})
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< {address: y, twitter: t, facebook: f'}
>>> // Remove field
>>> POST(seed: x, data: {twitter: ''})
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< {address: y, facebook: f'}
>>> // Complex request
>>> POST(seed: x, data: {address: '', facebook: f'', linkedin: l})
<<< {result: ok, maia: z}
>>> GET(maia: z)
<<< {facebook: f'', linkedin: l}
Views
Views are independent transactions that index a field of MAIA addresses. They provide a similar experience to the previous version of MAIA.
To use views, two methods are used:
- createView(maia: address, field: field to be indexed, callback: callback function used in browser execution) => Transaction hash.
- readView(view: view address, callback: callback function used in browser execution) => Field value.
The iteration is as follows:
Create a MAIA address
>>> POST(seed: x, data:{address:'my address', other:'example'})
<<< {status: ok, maia: z}
>>> GET(maia: A)
<<< {address:'my address', other:'example'}
Create a view
>>> createView(maia: A, field:'address')
<<< B // Hash of the transaction
>>> readView(view: B)
<<< 'my address'
Update the MAIA address
>>> POST(seed: x, data:{address:'my new address'})
<<< {status: ok, maia: z}
>>> readView(view: B)
<<< 'my new address'
Trees
MAIA 3 addresses use a tree data structure that allows efficient updates and readings. To understand the mechanism, nothing better that an example.
We create a MAIA 3 address.
To do this, first we connect to an IOTA node and we establish different parameters:
- provider: IOTA node.
- depth: Transactions depth.
- mwm: Transactions mwm.
- channelLayers: Number of intermediate layers to be used in the MAIA addresses.
- channelDepth: Maximum depth of the layers.
>>> var maia = new MAIA({
provider: p,
depth: 9,
mwm: 14,
channelLayers: 2,
channelDepth: 4})
Connected to the node, we publish the first message:
>>> maia.post(seed: x, data:{address:'AAA', twitter:'fjestrella'})
When the previous command is called, the root MAM channel is created and a configuration message is published in it.
// Root first message
// ID(=MAIA): A
// Seed_A = x
config {
protocol: 'maia',
version: 3,
layers: 2,
depth: 4
}
Next, a new channel, B, is created, being:
- Seed_B = seed(Seed_A, 0)
- seed(x, i) = toTrytes(SHA256(X + i)).substring(0, 81)
Note that SHA-256 is used for simplicity. Surely MAIA 4 will use Curl instead of it.
Once the id of the new channel, B, is known, a second message is published in the root channel A.
// Root channel second message
config {
next: B
}
Indexed B is published in it its configuration.
// B channel first message
config {
layers: 1, // A.layers - 1
depth: 4 // A.depth
}
As B.config.layers > 0, a new channel, C, is created, being Seed_C = seed(Seed_B, 0).
// B channel second message
config {
next: C
}
// C channel first message
config {
layers: 0
depth: 4
}
As C.config.layers == 0 and the number of messages in the channel (=1) is lower than C.config.depth + 1 (+1 due to configuration message) the data is published in this channel.
// C channel second message
data {
address: 'AAA'
twitter: 'fjestrella'
}
Once the message is created, the address of the root node, A, which is the MAIA address, is returned.
<<< {status: ok, maia: A}
A GET request would be resolved as follows:
>>> maia.get(maia: A)
- Read to channel A and navigate to the last message (0 + 2 = 2). The address of channel B is obtained in the last message.
- Read to channel B and navigate to the last message (2 + 2 = 4). The address of channel C is obtained in the last message.
- Read to channel C and navigate to the last message (4 + 2 = 6). The message contains data so it is returned.
<<< data {address: 'AAA', twitter: 'fjestrella'}
As is clear from the above, the process in the first message is much slower than in MAIA 2, but what will happen with message 2, or 10, or 100 ?. Let’s check it.
I have carried out two simulations using Kiri in an Up² setting the following scenario:
- Private IOTA testnet with 0 transactions.
- MWM = 1.
- Execution of the coordinator every 300 seconds.
- Update and read the address 365 times (we simulate one year updating daily).
The results speak for themselves.
MAIA PoC has been updated with the latest version, so you can try the new version now.
Emphasize that as I have always indicated, the site is a proof of concept. This means that many things have not been tried and the page can change or stop working at any time.
If you want to use MAIA in a controlled way you can download the source code from its repository. In it, the web code and some small directives for its configuration are available.
That’s all. In case you want to donate some IOTAs to support my work, send them to my donation address.