This is a snippet code which generates a code snippet for a popup lov item generates the « Initialization JavaScript Function » attribute for a popup lov item in an Oracle APEX application

Installation:

Download code from https://github.com/patrickmonaco/gpmfactory

import and run gen_initjs.sql script Optionnaly: import rest module from ORDS_REST_DEMO_ujs_2023_09_13.sql

This tool relies on Oracle JQuery UI dialog features.

Usage:

Either from sql editor as:

select gen_initjs(<APPLICATION_ID>,<LOV_NAME>) from dual 

or by calling the rest module as: 

https://xxxxxxxx.oraclecloudapps.com/ords/demo/ujs/lov/<APPLICATION_ID>/<LOV_NAME>

Samples



Without initialization code


With initialization code

Generated JS code

function(options) {
     options.defaultGridOptions = {
         columns: [{
             TABLE_NAME: {
                     heading: "Table or view Name",
                     width: 300,
                     alignment: "start",
                     headingAlignment: "start",
                     sortIndex: 1,
                     sortDirection: "desc",
                     canSort: true,
                     noStretch: true
                     },
             T: {
                     heading: "Type",
                     width: 100,
                     alignment: "center",
                     headingAlignment: "start",
                     canSort: true,
                     noStretch: true
                     }
         }]
     };
return options;
}

This demo is base on the standard demo tables ORDERS et ORDER_ITEMS.
The goal is to produce a chart with a monthly amount stacked with variance and a average monthly amount.

Build a combined chart and and two series from the tow following queries

Statement 1: implemented as a Stacked bar serie

select mm, b.mnt, 'mnt' serie from
(
select trunc(order_datetime,'MM') mm,
sum((unit_price *quantity)) mnt,
trunc(variance((unit_price *quantity)),2) vari
from orders d,
order_items i
where i.order_id = d.order_id
group by trunc(order_datetime,'MM')
order by 1
) b
UNION
select mm, b.mnt , 'variance' serie from
(
select trunc(order_datetime,'MM') mm,
trunc(variance((unit_price *quantity)),2) mnt
from orders d,
order_items i
where i.order_id = d.order_id
group by trunc(order_datetime,'MM')
order by 1
) b

Statement 2: implemented as a line serie

select b.mm,a.avgi, b.mnt, b.vari from
( select trunc(avg(mnt),2) avgi
from (
select trunc(order_datetime,'MM') mm,
sum((unit_price *quantity)) mnt
from orders d,
order_items i
where i.order_id = d.order_id
group by trunc(order_datetime,'MM')
)
) a,
(
select trunc(order_datetime,'MM') mm,
sum((unit_price *quantity)) mnt,
trunc(variance((unit_price *quantity)),2) vari
from orders d,
order_items i
where i.order_id = d.order_id
group by trunc(order_datetime,'MM')
order by 1
) b

This application is an experimental project dedicated to developers who need to build sql query generating XML.
In addition, the application generates a default xslt FOP template which can be used by a FOP server.
Download on Github

For generating pdf, we must provide a valid Report server endpoint with FOP installed on tomcat.
I used the apex5_fop project from mikhailidim available on github.
That can be https://github.com/darklordgrep/APEX-FOP/blob/main/apex_fop.jsp as well, which has been published recently in march 2023.

Usage

We choose a table or a view and some general rendering options.
then, FOP LAB follows all the Foreign Keys links in oder to generate an sql query and a default xslt layout.
If no FK are retrieved, only the master table is printed. In others cases, the master is printed in form display and all the chlid tables are displayed as xslt tables.
Ie: if we choose EMP table, the « managed people » are displayed as a grid under each master emp.

xslt templates are generated from xslt fragments which can be customized directly in the application.

The application is mainly intended to generate a sql query which generates in turn some xml stuff.
Because wrinting this kind of query is cumbersome, FOP LAB can be a good friend.
If we need to customize content of a child, the supported metthod is to create a view with a name identical to the child table and a suffix ‘_FOP_V’. In this case the view supersedes the original table.
IN the following exemple, we use ORDERS_ITEMS_FOP_V instead ORDERS_ITEMS to display aggregates (Total) and retrieve the product name.
It’s needed to add a Foreign key with ‘DISABLED’ status for linking the view with the ORDERS table.

Exemple of generated Sql Query

select "ORDERS"
from
(SELECT XMLSERIALIZE(
     CONTENT XMLELEMENT("ORDERS",
XMLELEMENT("HEADER", XMLELEMENT("report_date", TO_CHAR(SYSDATE,'Day DD Month YYYY')),
XMLELEMENT("TITLE", ''),
XMLELEMENT("DD", TO_CHAR(SYSDATE,'Day DD')),
XMLELEMENT("D", TO_CHAR(SYSDATE,'DD')),
XMLELEMENT("DAY", TO_CHAR(SYSDATE,'Day')),
XMLELEMENT("MONTH", TO_CHAR(SYSDATE,'Month')),
XMLELEMENT("YEAR", TO_CHAR(SYSDATE,'YYYY'))
),
         XMLAGG (
             XMLELEMENT("ORDERS_REC",
                 XMLFOREST (
                     e.ORDER_ID AS "ORDER_ID",
                     e.ORDER_DATETIME AS "ORDER_DATETIME",
                     e.CUSTOMER_ID AS "CUSTOMER_ID",
                     e.ORDER_STATUS AS "ORDER_STATUS",
                     e.STORE_ID AS "STORE_ID",
                     CUSTOMERS.CUSTOMER_ID AS "CUSTOMERS_CUSTOMER_ID",
                     CUSTOMERS.FULL_NAME AS "CUSTOMERS_FULL_NAME",
                     CUSTOMERS.EMAIL_ADDRESS AS "CUSTOMERS_EMAIL_ADDRESS",
                     STORES.STORE_ID AS "STORES_STORE_ID",
                     STORES.STORE_NAME AS "STORES_STORE_NAME",
                     STORES.WEB_ADDRESS AS "STORES_WEB_ADDRESS",
                     STORES.PHYSICAL_ADDRESS AS "STORES_PHYSICAL_ADDRESS",/* ------ ORDER_ITEMS_FOP_V / SYS_C0064516 ------ */
                     (select XMLAGG(
                         XMLELEMENT("ORDER_ITEMS_FOP_V_ORDERS_REC",
                             XMLFOREST(
                                 ORDER_ITEMS_FOP_V.QUANTITY AS "QUANTITY",
                                 ORDER_ITEMS_FOP_V.UNIT_PRICE AS "UNIT_PRICE",
                                 ORDER_ITEMS_FOP_V.MNT AS "MNT",
                                 ORDER_ITEMS_FOP_V.ORDER_ID AS "ORDER_ID",
                                 ORDER_ITEMS_FOP_V.PRODUCT_ID AS "PRODUCT_ID",
                                 ORDER_ITEMS_FOP_V.PRODUCT_NAME AS "PRODUCT_NAME"
                             )
                         )
                     )
                     from ORDER_ITEMS_FOP_V
                     where ORDER_ITEMS_FOP_V.ORDER_ID = e.ORDER_ID                    
                     ) ORDER_ITEMS_FOP_V
                 )
             )
         )
     )
) AS "ORDERS"
from "ORDERS" e ,
         CUSTOMERS,
         STORES
where rownum<100and
NVL(:PKID,e.ORDER_ID) = e.ORDER_ID
AND e.CUSTOMER_ID =CUSTOMERS.CUSTOMER_ID
AND e.STORE_ID =STORES.STORE_ID
)

                    

Notes et observations

Le projet consistait à valider les taches pour obtenir une instance Oracle APEX opérationnelle sur le cloud OVH en SSL avec un nom de domaine et au coût le plus bas.

Il n’y a rien de vraiment compliqué mais comme souvent, de glorieuses incertitudes sont venues pimenter le travail.

Voici les étapes que j’ai identifiées :

Préparer l’infrastructure

Obtenir un nom de domaine

Le nom de domaine sera désigné par <DOMAINE.TLD> dans la suite du document

Souscrire un serveur chez OVH

Désignons-le par « Serveur Y » dans la suite.

Sandbox S1-8 (2vCores, 8Go RAM, 40 Go disque) 14,30 € H.T. /mois en Cloud Public.
Cette variante de type Sandbox est valable uniquement pour des tests car elle n’offre pas la stabilité d’une instance conventionnelle.
Il faudrait plutôt s’orienter vers une instance Linux Centos (B2-7 à 24 € H.T. /mois ou B2-15 à 46 € H.T. /mois)

En comparaison, on peut garder en mémoire que la souscription au service Oracle APEX service revient à 333 € /mois (en date d’avril 2023)

J’ai choisi une image de type Centos 7

Pas la peine de prendre trop de cpu car Oracle XE est capé à 2 cores.

De même, l’espace disque dédié à la database est limité à 12 Go. Cependant, prévoir 40 Go car une installation basique occupe pas loin de 17 Go.

Télécharger les softs Oracle

Aucun n’entrainent des couts de licence.

Installer Oracle Database 21c Express

Installer Les prérequis pour Oracle XE 21 c
dans la page de download, cliquer sur Preinstall RPMs for RHEL and CentOS

Installer Oracle XE 21 c
Rien à signaler. Suivre le cookbook livré dans la doc officielle.

Vérifier le fichier /etc/hosts

Vérifier le port utilisé pour sqlnet et rectifier le port si besoin dans le fichier listener.ora.

/opt/oracle/homes/OraDBHome21cXE/network/admin/listener.ora

Installer Oracle APEX

Installer Oracle APEX 22 dans le PDB présent par défaut (xepdb1)

Ajouter dans le domaine créé plus haut une redirection sur un enregistrement de type A (l’adresse IP V4 du serveur Y)

Bien vérifier que le sous domaine créé dirige vers l’adresse IP en effectuant un ping à la fois depuis le serveur Y et depuis son poste de travail.
Dans la suite, je désigne par NOM.DOMAINE.TLD le nom (fqdn) que je vais attribuer à mon serveur Y.

Installer Oracle ORDS

Etre connecté sous le compte oracle:oinstall
Créer un répertoire /opt/ords/conf

Ajouter la variable d’environnement ORDS_CONFIG=/opt/ords/conf dans .bash_profile

Préciser dans la chaine de connexion « localhost » et préciser le PDB: xepdb1. Contrôler que le répertoire de configuration est ok.

Installer Apache Tomcat

Installer Tomcat 9
créer un fichier setenv.sh dans le répertoire /opt/tomcat/latest/bin

export ORDS_CONFIG=/opt/ords/conf
#export CATALINA_HOME=/opt/tomcat/latest
#export CATALINA_OPTS="$CATALINA_OPTS -Duser.timezone=UTC"
export JAVA_OPTS="-Dconfig.url=${ORDS_CONFIG} -Xms1024M 

Déployer ords.war dans le répertoire /opt/tomcat/latest/webapps

Une différence importante avec les version précédentes de ORDS est que la localisation des fichiers de configuration ne se trouve plus automatiquement dans le .war (quoique l’on puisse le régénérer avec la commande ords war) . Il est plus sûr de fournir le path via le script setenv.sh

Recopier les fichiers du répertoire images dans /opt/tomcat/latest/webapps/i

Tester depuis un navigateur

http://<IP_ADDRESS>:8080/ords
http://<IP_ADDRESS>:8080/ords/apex_admin (pour l’accès au service d’administration)

Occupation espace disque à ce stade de l’installation. Le 20 Go (20960236) était la valeur initiale avec une instance OVH modeste que j’ai upgradée ensuite à 40 Go.

Filesystem     1K-blocks     Used Available Use% Mounted on
devtmpfs         1865500        0   1865500   0% /dev
tmpfs            1891000        0   1891000   0% /dev/shm
tmpfs            1891000     8716   1882284   1% /run
tmpfs            1891000        0   1891000   0% /sys/fs/cgroup
/dev/sda1       20960236 17065564   3894672  82% /
tmpfs             378200        0    378200   0% /run/user/1000

Mise en place de TLS

La méthode que je privilégie est d’installer un Apache Listener en Reverse Proxy. C’est lui qui sera chargé de la vérification des certificats et du protocole TLS.

Installer Apache HTTPD

Préciser un Virtual Host dans le fichier /etc/https/conf/httpd.conf

Installer certbot et obtenir un certificat auprès de Lets’Encrypt.

La procédure paramètre automatiquement la configuration d’Apache.

Tester depuis un navigateur:

https://<NOM.DOMAINE.TLD>

Rediriger les requêtes TLS vers Tomcat

Il s’agit de rediriger les requetes SSL vers Tomcat qui « écoute » en http sur le port 8080.

J’utilise mod_proxy.

<VirtualHost *:80>
        Redirect "/" "https://<NOM.DOMAINE.TLD>/"
        #ProxyPreserveHost On
        #RequestHeader unset Origin
RewriteEngine on
RewriteCond %{SERVER_NAME} = <NOM.DOMAINE.TLD>
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Remarque importante: Si Service unavailable, il faut probablement modifier une valeur de paramètre :

setsebool -P httpd_can_network_connect on

Dans le répertoire /etc/httpd/conf.d , il faut modifier le fichier ssl.conf pour indiquer la façon dont se fera la redirection vers tomcat:

<VirtualHost *:443>

# General setup for the virtual host, inherited from global configuration
DocumentRoot "/var/www/html"
ProxyPreserveHost On
ServerName <NOM.DOMAINE.TLD>
#ProxyRequests Off
#RequestHeader set Host "<NOM.DOMAINE.TLD>:443"
ProxyPass /  http://<NOM.DOMAINE.TLD>:8080/
ProxyPassReverse /  http://<NOM.DOMAINE.TLD>:8080/

SSLEngine on
SSLProxyEngine on

Remarque Importante: Dans le fichier de configuration httpd.conf, il y a la directive suivante: IncludeOptional conf.d/*.conf

Cela signifie que TOUS les fichiers .conf vont être inclus. Donc, veiller à ne pas sauvegarder des fichiers de backup dans ce même répertoire, sinon on obtient des erreurs du type: port déjà utilisé, ou bien Nom de serveur déjà utilisé qui empêchent le démarrage de Apache Httpd.

A cette occasion, j’ai vite constaté (avec la commande journalctl -xe ) que le serveur faisait l’objet de nombreuse tentatives de connexions ssh . J’ai neutralisé les accès en agissant sur les deux fichiers

  • /etc/hosts.allow
  • /etc/hosts.deny:

Complément paramétrage Tomcat

dans la balise <Connector …> ajouter:

proxyPort="443"
scheme="https"

Tester avec un navigateur:

https:<NOM.DOMAINE.TLD>/ords

Permettre les communications HTTPS en sortie

Il faut autoriser les communications entre la database et l’extérieur

ACL network

Créer un wallet DB pour les certificats

Créer un wallet et y enregistrer les certificats nécessaires. Cette étape est obligatoire pour réaliser des appels REST qui doivent impérativement utiliser TLS.

.

From the 22.x version of ORDS, ords.war file must be generated in order to include the configuration directory path.

The command is:
ords war <NEW_ORDS.WAR_NAME> (ie: ords war ords_new.war)

Before, I set the ORDS_CONFIG environement variable. In my case:
export ORDS_CONFIG=/opt/ords/conf

When deploying on Tomcat, it should retrieve the path but in my case, it doesn’t. I get a 404.

I mean, the behaviour is the same with the original ords.war file or the new one after rebuilding.

So, a possible way is to pass the path url to Java runtime when starting Tomcat.

Add a new file named exactly : setenv.sh in tomcat_home /bin

In this file, add:

export ORDS_CONFIG=/opt/ords/conf
export JAVA_OPTS="-Dconfig.url=${ORDS_CONFIG} -Xms1024M -Xmx1024M"

Then, shutdown Tomcat and restart it.

For automatic starting follow this link.

Context and Objectives

In an Oracle APEX application, there is possibility to enter Help text at development stage. The help text may be used to provide page level context sensitive help.
In almost every component, there is a specific property (Help Text) aimed to receive the text.

Usually, the developer is responsible for this task and that has drawbacks :

  • The text can only be provided in the Developer interface.
  • There is no rich text editor support at this level
  • The developer himself is not, most of time, the best qualified person to handle this job

Given these above considerations:

  • We need a more confortable tool for authoring Help Text
  • It’s better to delegate this job to a writer who will have better user sensitivity.
  • the text needs to be continually improved as it is used, without doing back and forth in the development console.

Let’s consider a possible solution to achieve our goal.

In this paper, we’ll focus on Help Text at page level only and we’ll not consider the other level of component (items) neither Inline Help Text.

Global approach

One solution is to add an application table wich contains specific help text.
The authors will need a regular access to application in order to modify the help text through a dedicated form page.

In standard, the help texts are accessible through an APEX view: APEX_APPLICATION_PAGES

Access key is : APPLICATION_ID + PAGE_ID
text: HELP_TEXT

We build a new table which contains customized help texts. Let’s say : PLA_HELP

CREATE TABLE PLA_HELP
( APP_ID NUMBER,
  PAGE_ID NUMBER,
  HELP_TEXT CLOB,
  CREATED_BY VARCHAR2(50),
  CREATED_ON DATE,
  CONSTRAINT PLA_HELP_PK PRIMARY KEY (APP_ID,PAGE_ID)
  USING INDEX ENABLE
) 

We build a view PLA_HELP_V that superimposes help text derived from repository and help text coming from our specific table.
Priority is given to Customized Help Text.

CREATE OR REPLACE FORCE EDITIONABLE VIEW PLA_HELP_V (APP_ID, PAGE_ID, CREATED_BY, CREATED_ON, PAGE_TITLE, HELP_TEXT, IS_FACTORY) AS
select
  p.APPLICATION_ID,
  p.PAGE_ID,
  h.CREATED_BY,
  h.CREATED_ON,
  p.PAGE_TITLE,
  case when h.HELP_TEXT is null 
     then p.HELP_TEXT
     else h.HELP_TEXT
  end HELP_TEXT,
  case when h.HELP_TEXT is null 
     then 'Y'
     else 'N'
  end IS_FACTORY
from APEX_APPLICATION_PAGES p,
     PLA_HELP h
where p.APPLICATION_ID = h.APP_ID(+)
and p.PAGE_ID = h.PAGE_ID(+)

Displaying help text needs a specific page dedicated to that.
When we launch the wizzard, the page and navigation icons are automatically created if a page at least is added, but it’s not the case otherwise.

Help about a page. A edit icon allows to navigate to edit mode for authorized users.
Edit Help text page.

My first choice has been to create a Instead of Trigger but this way reached an obstacle: I got an -1031 error insufficient privileges, because of presence of a system APEX view. I could workaround by granting some privileges directly to user, but I gave this approach up and I put all the code in the APEX form.

In the process section, we remove the default form DML process and replace it by three processes, each dedicated to an action (Update, insert or delete)

ie: the code for update below:

BEGIN     
 update PLA_HELP
     set
       HELP_TEXT = :P35_HELP_TEXT,
       CREATED_ON = :P35_CREATED_ON,
       CREATED_BY  = :P35_CREATED_BY
     where APP_ID = :P35_APP_ID and
           PAGE_ID = :P35_PAGE_ID;
 COMMIT;
END;

Conclusion

The new system provides a more flexible solution for providing accurate information to users.

We could imagine to refine our help system by adding multiple levels of reading, depending the user profile.
This solution can be improved, as well, by merging additional infos provided later by developper (because of fixing bugs or adding features) with an already existing customized text.

Even with the last version of Oracle APEX (22.2) which embeds Version 5 of FullCalendar, displaying can be slighty improved to give a better rendering on mobile devices.

Below are two samples emulated on iphone 6: First one is a displaying with default values, Second is a a calendar with some additional actions.

In the default version, the title for Contextual dates are too larges and some buttons are not displayed. The navigation buttons are confusing.
In the customized version, the navigation button are better reachable at right side with more intuitive icons, size of contextual date is reduced and view buttons are displayed entirely.

Additional actions

In the improved version, we:

  • Hide navigation option in Calendar Views and Navigation section
    The standard arrows will be replaced by customized buttons
  • Add three buttons in EDIT section of the Calendar region
    • Previous
      • DA on button: apex.region("calendar").widget().data("fullCalendar").prev();
      • ico: fa-arrow-left-alt u-color-1-text
    • Today
      • DA on button: apex.region("calendar").widget().data("fullCalendar").today();
      • icon: fa-pie-chart-0
    • Next
      • DA on Button: apex.region("calendar").widget().data("fullCalendar").next();
      • icon: fa-arrow-right-alt u-color-1-text
  • override class style at the page level in INLINE CSS section

.fc .fc-toolbar-title {
font-size: small;
}

un article sur le Bitcoin que j’avais écrit en 2018 et qu’il faut que je réactualise …

« Mon cher Jack,

 Comme je te l’ai écrit dans ma dernière lettre, on se retrouvera début septembre à Skagway. J’ai raflé tout le stock chez le chinois de Market Street. Il était tout excité et m’a promis que cela tiendrait 14 Téra Hash mais tu ne sais jamais très bien avec lui… Et puis, j’ai aussi rassemblé suffisamment de chiens pour monter nos vivres et toutes nos cartes ASIC. Notre claim est à trois jours du Chilkoot. Il y a plein de torrents autour et de quoi dresser des barrages pour donner du jus à nos cartes. Crois-moi, elles vont gentiment ronronner et nous tenir chaud pendant le blizzard et au printemps, on sera riche, Jack ! et cette fois-ci, je te prédis que nous traverserons Dawson sans verser une goutte d’alcool, sans même aller rendre une visite à Julia, nos poches gonflées de bitcoins, comme des seigneurs sous les étoiles.

Bien à toi,

SF Juin 2018″

Et voilà, mon histoire s’arrête provisoirement ici. Comment vais-je parvenir à placer tous ces trucs de hash, de nonce, de courbes elliptiques ou de peer-to-peer ? La plume du grand Jack n’aurait pas tremblé, elle !

De la confiance

J’entendais parler du bitcoin depuis longtemps avec indifférence mais si je me rappelle bien, c’est en mai 2017, lorsque des hackers ont disséminé le virus WannaCry puis réclamé une rançon en bitcoins que, dans mon esprit, la légitimité de cette monnaie venait ironiquement d’être établie. J’entrevoyais que si le bitcoin permettait un échange de valeur entre citoyens ordinaires d’une part et escrocs de l’autre, à la vue de tous, alors cette monnaie universelle était vraiment digne de confiance !

Ce qui me frappe aujourd’hui en observant le système Bitcoin, c’est sa robustesse. Faut-il que ce cela soit bien conçu pour fonctionner sans véritable accroc depuis sa création en 2009 ! C’est la plus fameuse blockchain que l’on puisse imaginer car elle est publique et cristallise sur sa technologie 130 Milliards d’Euros, ce qui représente un sacré tas de confiance.

Le bitcoin est le nom de la monnaie qui est produite par le système Bitcoin qui est, lui, un écosystème comprenant des développeurs, du logiciel, un protocole, une communauté d’intérêt à entrée libre. Le bitcoin, contrairement à l’or,  ne possède aucune valeur intrinsèque. Il doit être considéré essentiellement comme un système de paiement. Il peut éventuellement être perçu comme valeur refuge.

De l’énergie

Toute cette belle confiance fossilisée dans le bitcoin est basée in fine sur une dépense énergétique ahurissante. Ce 16 avril, au moment ou je commence ces lignes, 11.500 sites informatiques bourrés d’ordinateurs tournant à plein régime participent à un jeu de devinette à l’échelle mondiale en consommant l’équivalent de 50 TWh/an , soit 10% de la production Française d’électricité. Et c’est sur ce mécanisme incroyable à la fois absurde et génial que fonctionne le bitcoin. Pourquoi ? En raison d’un enchaînement de conséquences liées au caractère décentralisé d’une blockchain publique et donc du Bitcoin en particulier.

On va produire de la monnaie de façon décentralisée, mais cependant maîtrisée, et confier à un grand nombre de volontaires, appelés des mineurs dans le jargon Bitcoin, le soin de garder une copie du registre de tous les virements effectués avec cette monnaie depuis sa date de démarrage en 2009. Allons-nous confier la tenue des comptes à de parfaits inconnus ? Oui, c’est exactement ce que l’on va faire sous la forme de ce qui peut s’apparenter à une franchise.

A cette fin, on élabore un Grand Livre comptable dans lequel sont enregistrés tous les mouvements de bitcoins d’une partie vers une autre, c’est à dire d’une personne privée ou morale, vers une autre. D’un point de vue technique, ce Grand Livre est matérialisé par un ensemble de fichiers organisés sous la forme d’une blockchain. C’est à l’intérieur de celui-ci que sont enregistrées toutes les transactions financières qui sont signées à l’aide de clefs asymétriques, puis regroupées en blocs qui sont tricotés ensemble à la manière d’une écharpe qui grandirait inexorablement. Toute tentative pour y introduire une opération frauduleuse qui ressemblerait à celle-ci : « je verse, ex nihilo, un million de bitcoins à moi-même, le 16 avril »  est considérée d’un point de vue cryptographique comme quasiment impossible, quand bien-même le Grand Livre est accessible à tous.

Liberté ensuite, à qui le veut, de télécharger sur son ordinateur le logiciel Bitcoin Core qui récupérera une copie de cette blockchain  puis de se déclarer comme volontaire (mineur) pour en assurer une réplication conforme à toutes les autres copies dans le monde. En échange du service qui est, concrètement, celui de maintenir un niveau de disponibilité indiscutable (en raison des milliers de répliques du Grand Livre), le système Bitcoin rétribue chaque mineur selon un barème évoluant dans le temps mais en assortissant le deal d’une autre contrepartie qui est celle de participer à un jeu coûteux en temps. Oui un jeu, une sorte de loterie !

Du consensus

L’objectif primordial, dans un système décentralisé, est d’obtenir un consensus sur un exemplaire VRAI et donc unique du Grand Livre tout en évitant un emballement du nombre de synchronisations (peer-to-peer) entre les comptables (les mineurs) pour savoir quelle est la bonne version et en évitant également la formation d’une situation monopolistique (> 51% de mineurs complices).

Venons-en à ce que je considère comme la plus grande et géniale monstruosité qui constitue un sérieux défi à l’entendement: On introduit un mécanisme de ralentissement qui vise à garder à la fois un nombre raisonnable de mineurs et un nombre raisonnable d’échanges entre eux pour ne pas saturer le réseau. C’est cette même mécanique qui permet, indirectement, de réguler la rareté de façon déterministe puisque le nombre de bitcoins à atteindre, selon les statuts de départ, est de vingt-et-un millions, pas un de plus, selon une cadence programmée jusqu’en 2040. On va donc obliger les mineurs à perdre du temps dans un jeu de devinette. Celle-ci nécessite que chaque mineur soit équipé d’un ordinateur, d’un accès au réseau internet et d’un logiciel spécialisé, le Bitcoin Core. L’émergence du consensus est ainsi acquise à l’aide du mécanisme précédent désigné par l’expression « preuve de travail  » (POW). C’est également le cas pour Ethereum qui est une autre blockchain très populaire. La question est de savoir comment objectiver cette quantité de « travail » et c’est maintenant qu’il faut rappeler les vertus du hash.

Du hash

« De toute ma vie, je n’avais jamais vu une telle quantité de hash partir en fumée! « 

Le système Bitcoin est conçu pour « fatiguer » les machines des mineurs, éprouver leur détermination pour ainsi dire. Bitcoin utilise ad nauseum la technique de hashingIl s’agit d’un procédé logiciel qui consiste à produire, à partir de n’importe quoi (un texte, des nombres, une image, un livre complet) une suite de caractères d’une longueur fixe de 256 bits qui représente un condensé unique appelé hash. Ce dernier se présente soit comme une suite de deux cent cinquante-six chiffres 1 et 0, soit comme un mélange de trente-deux chiffres et lettres ou soit comme un nombre très grand pouvant aller jusqu’à 2 puissance 256. C’est juste une affaire de représentation. SHA256 est l’une des variantes de ce procédé. C’est un beau bijou logiciel digne d’une montre à complications et qui mériterait lui aussi d’être porté au poignet. En décrire le fonctionnement sort du cadre de cet article mais je peux simplement dire que, si deux choses auxquelles on applique le hashing présentent une différence, aussi insignifiante soit-elle, alors les valeurs de hash obtenues seront totalement différentes. Par exemple, si je modifie un seul caractère du texte de la Bible, une autre personne peut le détecter immédiatement en constatant que la nouvelle valeur de hash vient de changer radicalement. C’est donc très pratique pour garantir l’inviolabilité d’une information. A contrario, je mets au défi quiconque de trouver, à partir d’une valeur de hash prise au hasard, quelle est la chose qui lui a donné « naissance ».
Cependant … il est de l’ordre du possible de lancer un challenge qui ressemblerait à celui-ci : « Trouver une chose dont la valeur de hash commence par une série de 18 zéros. »
C’est exactement ce genre de devinette qui sera soumise aux ordinateurs ! Après des milliards de milliards de « coups de hachoir », si on parvient à obtenir un hash présentant cette caractéristique, le jeu de devinette est gagné. S’il faut augmenter la difficulté, le défi deviendrait simplement : « Maintenant, encore plus fort: c’est 19 zéros et non plus 18. « .

Si on se relie à nouveau à notre Grand Livre, le principe de la devinette évoquée plus haut consiste à « tomber » par chance sur un nombre appelé nonce, (2) tel que, combiné avec le contenu d’une nouvelle page du Grand Livre contenant les enregistrements des toutes dernières transactions, celui-ci produise à l’issue d’un hashing une valeur de hash présentant des caractéristiques morphologiques précises (Target) comme illustré précédemment.

Pour donner une idée, il faut environ actuellement un trillion d’essais, environ, avant de tomber sur un bon nombre. Tout dépend si on a de la chance, mais disons que c’est calibré pour durer environ dix minutes. Le logiciel de Bitcoin communément utilisé par chacun des mineurs agit ainsi à la manière d’un pacemaker qui fixe le niveau de rareté en fonction du nombre de mineurs à un instant donné et de la puissance intrinsèque des ordinateurs qui, elle, progresse régulièrement en raison des progrès de la technologie. La difficulté augmente tous les 2016 blocs, c’est à dire toutes les deux semaines environ.

Dès qu’un mineur trouve une combinaison correcte, son logiciel avertit tous les autres (peer-to-peer). A partir de ce moment là, tous les autres mineurs sont tenus de vérifier que le nombre est effectivement correct, et s’inclinent alors en acceptant la victoire du compétiteur et ajoutant au Grand Livre la nouvelle page, c’est à dire le bloc qui vient d’être validé par le vainqueur. Résultat: 12,5 bitcoins dans la poche de celui qui a trouvé le nombre, plus une petite rémunération associée (fee) à chacune des transactions enregistrées dans le bloc, et on est reparti pour le tour suivant ! Précisons que c’est uniquement à ce stade qu’a lieu le processus de création monétaire. Au 16 avril 2018, le bitcoin (BTC) s’échange contre 6.564 € et donc le gagnant ramasse environ 80.000 €.De l’électricité est consommée (il vaut mieux être en Chine), de la chaleur produite (il vaut mieux être en Islande) , du bruit n’en parlons pas (il vaut mieux être sourd) , tout cela pour être le premier à lever le doigt. C’est complètement idiot, non ? C’est à la fois absurde et génial. C’est le prix à payer pour obtenir un consensus dans une communauté d’intérêts dénuée de confiance (trustless). Il existe d’autres méthodes sur lequel le système Bitcoin aurait pu s’appuyer pour obtenir un consensus, mais celle-ci s’avère très robuste lorsque l’environnement ressemble d’avantage au Far-West qu’à une association diocésaine.

Dans ce qui précède, j’ai eu recours à un peu d’anthropomorphisme en parlant de mineurs, mais j’aurais dû employer le terme plus exact de « logiciel Bitcoin utilisé par le mineur« .

La ruée

Inutile d’insister sur les enjeux ni de préciser qu’il existe une course aux armements en matière de puissance de calcul. Les processeurs classiques sont désormais hors jeu dans cette compétition. On détournait encore très récemment l’usage des cartes graphiques élaborées (celles utilisées par d’autres vrais gamers) pour leur faire exécuter ces fameuses opérations de hashing, mais elles sont désormais supplantées par des circuits spécialisés (ASIC) qui ne savent rien faire d’autre que du hashing.

Une carte spécialisée ASIC effectue 14 Teras, soit environ 14.000 milliards d’opérations de hashing en une seconde. Une machine de ce type vaut 2.400 €. Comme il faut concentrer beaucoup de puissance pour se garantir un niveau de rémunération qui ne soit pas trop aléatoire, beaucoup de mineurs se contentent de rejoindre des sortes de coopératives (mining pool) et le butin, s’il y en a, est partagé selon des règles propres à la coopérative. La puissance totale recensée au mois d’avril 2018 est de l’ordre de 30 millions de Tera H/s, soit 30 Peta TH/s. C’est ce qu’on appelle le Hashrate. Le logiciel Bitcoin Core tient compte de cette information pour moduler le niveau de difficulté. En avril 2018, la Chine où le charbon est abondant et par conséquent l’électricité bon marché (0.11 $ /kwh), concentre plus de 51% des pools de mineurs (AntPoolF2PoolBTCC). Ce dernier point ne signifie pas que nous sommes en présence d’une situation monopolistique mais entraîne cependant des interrogations. Le système Bitcoin n’est de toute façon qu’une interminable liste de « que se passerait-il si… ».

De la raison

le Bitcoin est donc cette expérience révolutionnaire qui se déroule sous nos yeux en temps réel et qui est passée directement du stade de white paper en 2009 à celui de laboratoire puis celui de banque alternative crédible. Le Bitcoin a popularisé l’emploi d’une approche décentralisée pour réinventer des modèles d’échange de valeurs, et affronter de nouvelles classes de besoins que notre esprit conformiste ou notre fameux bon sens nous aurait empêcher d’envisager sous une autre forme que celle passant par le « nécessaire » tiers de confiance. C’est le plus bel exemple de blockchain en activité.

 » Est-ce bien ce monde meilleur que tu souhaitais Jack ? »


(1) Les avis sur cette cryptomonnaie sont partagés, évidemment. Des économistes prétendent qu’elle alimente une bulle spéculative et fait courir des risques importants au système financier. Le prix Nobel JeanTirole ou bien Jamie Dimon (JP Morgan) ont écrit récemment des articles très négatifs sur le bitcoin. Ce dernier est un « objet » tellement révolutionnaire et échappant à toute expérience passée que même des économistes chevronnés ne parviennent pas à s’accorder pour dire, par exemple, si le bitcoin est assimilable à une pyramide de Ponzi ou non.

(2) Devant la montée en puissance des processeurs spécialisés (ASIC) en hashing, il a fallu se libérer de la valeur du nonce qui permettait de monter à « seulement » quatre milliards en lui ajoutant d’autres combinatoires. Ce fut l’objet du protocole stratum qui permet à un pool de mineurs de travailler efficacement en partageant des « plages de calcul »

Oracle APEX Display Map item allows displaying a map with a point given as a GeoJSON object.

What happens if we have only two columns Lat and Long ?

We have just to transform them as a json object through a custom function as below:

create or replace function TO_GEOJSON
(lg in VARCHAR2,
lat in VARCHAR2)
return VARCHAR2
is
begin
return '{"coordinates":['||lat||','||lg ||'],"type": "point" }';
end;

In source properties of the map item, we choose :

  • Type: Expression
  • PL/SQL expression: to_geojson(:PXX_LONGITUDE, :PXX_LATITUDE)