1. Introduzione


2. Ecosistema Generale


3. 4RYA


4. Legal & Compliance


5. Synkrony Exchange


6. Synkrony Pay Component


7. Synkrony Payments


8. Independent Chain


9. Affidaty Blockchain Services (ABS)


10. Smart Contracts


11. Algoritmo di consenso


12. Core


13. Tutorials

Creators:


Affidaty S.p.A

Board
D. Marciano (C.E.O), R.Setti (C.M.O), N. Quattrini (Relations Manager).

Technical
L.Vignali (C.T.O), F.Costanzo (P.O. & S.M.), G.Capaccioli (B.I. Manager), A. Vitsiuk (Senior Blockchain Developer), R.Greco (Senior Blockchain Developer), F.Gennero (Senior Blockchain Developer), G.Spinelli (UX Designer), P.Bergamaschi (UX Designer), S.Setti (Blockchain Software Engineer), A.Biagianti (Senior Blockchain Developer) , M.Baratto (Senior Blockchain Developer), E.Maccherini (Senior Blockchain Developer).

Administration
F. Zipoli (Chief Executive Assistant), S. Pappolla (Assistente amministrativo), M.Giudici (Addetto risorse umane e Responsabile UNI-EN ISO 9001:2015), L.A.Musu (Impiegata amministrativa), Y. Toni (Impiegata amministrativa), A.Terenzi (B.Analyst).

Advisor
Avv. A.Baldi (Legal Advisor), M.Balduini (Financial Advisor).


1.1 Come va letto T.R.I.N.C.I book


Negli anni di lavoro in ambiente blockchain, il team di Affidaty S.p.A si è reso conto che uno dei maggiori problemi che qualsiasi progetto ha nel rendersi immediatamente comprensibile al pubblico è proprio la documentazione: spesso troppo frammentaria o, al contrario, eccessivamente dettagliata oppure frammentata in un numero troppo elevato di documenti.

Questo ha portato il team a testare e sviluppare una tipologia di documentazione fruibile al pubblico, in base agli interessi del lettore stesso.

Nasce, quindi, il libro di T.R.I.N.C.I. , scritto per permettere la lettura dei contenuti in modo fluido.

Il libro è stato strutturato in 11 capitoli principali, ciascuno leggibile separatamente rispetto agli altri, proprio poiché non è forzatamente legato ai restanti capitoli:

  1. Introduzione (il T.R.I.N.C.I. book, a chi si rivolge, come è nata T.R.I.N.C.I.);
  2. Ecosistema Generale (una introduzione ai pilastri ed alle tecnologie scelte);
  3. 4RYA (il sistema di identità in blockchain T.R.I.N.C.I.);
  4. Legal & Compliance (aspetti legali che rendono T.R.I.N.C.I. conforme);
  5. Synkrony Exchange (il Synkrony Exchange nativo in T.R.I.N.C.I.);
  6. Synkrony Pay Component (la app di pagamento per e-Commerce ed utenti di base);
  7. Synkrony Payments (la Piattaforma di Conto Corrente bancario, con carta Mastercard ed IBAN dedicato);
  8. Independent Chain (il network di notarizzazione);
  9. Affidaty Blockchain Services - ABS (Ambiente di costruzione pannelli per gli Smart Contracts);
  10. Smart Contracts (una carrellata degli smart contracts fondamentali in T.R.I.N.C.I.);
  11. Algoritmo di consenso (il motore interno di T.R.I.N.C.I.);
  12. Core (la tecnologia approfondita);
  13. Tutorials (tutorial di varia natura - in lingua inglese)

Questa tipologia di struttura permetterà al lettore di: leggere il libro così come è presentato, saltare capitoli a lui non immediatamente di interesse, iniziare da capitoli che lo incuriosiscono maggiormente, per poi saltare verso altri.

Durante la lettura verranno richiamati punti fondamentali che, se coglieranno l'interesse del lettore, potranno essere approfonditi leggendo i capitoli dedicati o seguendo i link proposti.

1.2 A chi si rivolge il libro di T.R.I.N.C.I.


Blockchain è oramai da anni una parola di forte impatto per il pubblico globale. Non è più una tecnologia rivolta soltanto alle persone del settore: sono infatti circa 300 milioni le persone al mondo che usano blockchain e crypto monete (link).

Ecco perché il libro di T.R.I.N.C.I. è rivolto a una moltitudine di utenti:

  1. costruttori di blockchain;
  2. aziende interessate ad integrare una blockchain cucita addosso al proprio business;
  3. system integrators interessati a dotarsi di una blockchain dotata di strumenti "business oriented";
  4. utilizzatori di protocolli e dApp;
  5. traders;
  6. divulgatori o content creators;
  7. appassionati.

Attraverso la presente documentazione, il lettore di potrà dapprima ottenere in modo completo ed indipendente le informazioni su funzionalità, tecnologia e potenzialità dell’ecosistema T.R.I.N.C.I, per poi sentirsi libero di porre quesiti maggiori e più approfonditi tanto alla community che ai creatori della tecnologia.

1.3 Come è nata T.R.I.N.C.I.


T.R.I.N.C.I. è nata da un’esperienza imprenditoriale di Affidaty che, nel 2016, ha deciso di diventare integratore di tecnologia blockchain di terze parti.

L’azienda ha iniziato ad integrare Bitcoin ed Ethereum per sviluppare progetti in blockchain molto indirizzati all’ambiente Enterprise.

Focalizzandoci sulle varie tecnologie blockchain presenti sul mercato (Bitcoin, Ethereum, Polkadot, Algorand) ci siamo resi conto che la maggior parte di questi progetti non veniva alla luce; abbiamo quindi fatto una analisi pratica per comprendere il motivo per il quale progetti di classe enterprise non riuscissero a nascere concretamente in blockchain, chiedendoci se i problemi fossero tecnologici.

I problemi evidenziati erano principalmente di 2 tipologie:

  1. carenza di adozione della tecnologia blockchain;
  2. assenza di strumenti utilizzabili nella vita reale da utenti ed imprese.

Dati i problemi evidenziati, siamo andati alla ricerca di una tecnologia adatta a facilitare le imprese ad andare sul mercato. Non esisteva una tecnologia unica che risolvesse il tutto, bensì varie tecnologie (come Bitcoin, Ethereum, Algorand, Polkadot) che risolvevano segmenti dei problemi evidenziati.

Le strade erano due:

  1. fare una integrazione, un mix tra tutte le tecnologie individuate (ma con il rischio di produrre un qualcosa di inutilizzabile, poiché non nate per lo scopo);
  2. creare da zero una tecnologia pulita che avesse tutte le caratteristiche per: - risolvere i problemi evidenziati dalla checklist fatta; - essere una rampa di lancio dell’adozione della blockchain nel mondo delle aziende e degli utenti delle aziende.

La scelta è stata creare una tecnologia pulita, costruita completamente da zero.

  • Lo svantaggio di questa scelta è stato certamente lavorare molto più a lungo rispetto che ad adattare una tecnologia esistente al nostro obiettivo;
  • Il vantaggio, invece, si è concretizzato nel costruire un ecosistema tecnologicamente pulito, user friendly, conforme alle direttive europee e completamente funzionale all’ambiente Enterprise; di conseguenza usabile in modo veloce e tangibile da utenti aziende, esercenti, trader ed utenti comuni.

Tutto l’ecosistema, infatti, è basato su quelli che abbiamo definito “i 4 pilastri” necessari per unire tecnologia, Legal & Compliace, Finance.

2.1 - I 4 Pilastri


T.R.I.N.C.I. è una tecnologia che si erige su 4 pilastri fondamentali:

1 Tecnologia blockchain, capitoli:

  • 2.1.1 Tecnologia Blockchain
  • 11 Core

2 Identità digitale, capitoli:

  • 2.1.2 Identità digitale 4RYA

3 Legal & Compliance, capitoli:

  • 2.1.3 Legal & Compliance
  • 4 Legal & Compliance

4 Business: Circuito Synkrony, capitoli:

  • 2.1.4 Business: Circuito Synkrony
  • 5 Synkrony Exchange
  • 6 Synkrony Pay Component



2.1.1 Tecnologia Blockchain.


La tecnologia blockchain di T.R.I.N.C.I. ruota attorno al concetto di HDSB: High Density Scoped Blockchain. Tale concetto è approfondito nei seguenti capitoli:

  • 5 Synkrony Exchange;
  • 7 Independent Chain;
  • 9 Smart Contracts.

Per sintetizzare in modo chiaro cosa siano ed a cosa servano le HDSB, dobbiamo partire dalle blockchain pubbliche: quelle ad oggi conosciute non sono ottimizzate per ospitare e gestire transazioni a quantità elevate di dati: per esempio non vengono inviati in blockchain documenti interi, bensì gli hash (l’impronta digitale) di quei documenti.

Per far sì che una blockchain sia adatta al mondo business (obiettivo di T.R.I.N.C.I.) è necessario poter usare ed inviare (in blockchain) dati completi, con relativi smart contracts che possano lavorare con essi: da qui, il concetto di "blockchain piena di dati”. Costruire una blockchain piena di qualsiasi tipo di dato, però, la renderebbe troppo grande con il passare del tempo e quindi sempre meno scalabile: inutilizzabile in ambiente business.

Ecco perché abbiamo dato vita al concetto Blockchain di scopo ad alta densità (di dati). “Scoped” è la parola chiave: in T.R.I.N.C.I., infatti, possono essere costruite tante blockchain dense solamente dei dati relativi allo scopo per il quale sono state costruite. Il risultato è che possono convivere e comunicare tra di loro in T.R.I.N.C.I. blockchain diverse, con alta densità di dati solo relativi al proprio scopo.

Quindi ciascuna HDSB (con la relativa densità di dati) non avrà alcun impatto sulle altre (e quindi sui dati delle altre), nonostante venga costruita per: comunicare pubblicamente con una o tutte le altre blockchain di scopo dell’ecosistema, ancorandosi alla blockchain pubblica “Alpha”; oppure, se necessario, vivere solo in proprio network privato;

Ecco perché i dati di ciascuna HDSB, seppur densi, non impattano negativamente con quelli di altre HDSB dell’ecosistema.

In questo modo ogni HDSB è in grado di adattarsi a qualsiasi scopo che un’azienda richieda: sia che lo scopo sia ottimizzato per funzionare in rete pubblica (con sistema di ancoraggio in rete pubblica), sia che esso sia ottimizzato per funzionare in una rete privata.

Il software che costituisce la tecnologia Blockchain è un connubio di codice di programmazione e documentazione tecnica, ed è stato rilasciato pubblicamente su Github affinché tutto il mondo degli sviluppatori possa comprendere e verificarne la genuinità oltre che contribuire a migliorarlo negli aspetti di sicurezza e funzionalità.

Il software, una volta compilato ed eseguito, consente di avviare un computer (nodo) capace di costituire in autonomia una rete decentralizzata e distribuita ed eseguire transazioni su smart-contract realizzati con la stessa tecnologia rilasciata su github, garantendo di fatto la sopravvivenza tecnologica sia del codice che della rete oltre a mantenere attivi sistemi DAO e transazioni disintermediate, con un sistema di incentivi creato a partire dal valore degli assets (i token) generati e scambiati sulla rete stessa, per coloro che decidono di avviare e mantenere attivo un qualsiasi nodo.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato:

  • 11 Core



2.1.2 Identità digitale.


In blockchain non esiste un proprietario o un governante. Questa caratteristica separa in maniera netta blockchain da cloud. Questa differenza è di fondamentale importanza nello sviluppo di un protocollo dedicato all’identità sovrana.

In un sistema blockchain viene volutamente a mancare la figura del proprietario, poiché non si vuole inserire qualcuno che possa modificare i dati (anche in buona fede). In questo caso, quindi, tante situazioni che in un sistema informatico potrebbero sembrare scontate, nel sistema blockchain non lo sono più: la creazione di un utente ne è un esempio. In un sistema cloud classico un soggetto terzo (per esempio un’azienda) salva i dati e le informazioni dell’identità che un utente ha immesso al momento della registrazione; da lì in poi l’utente si logga.

In un sistema blockchain, invece, non esiste quel “qualcuno” centrale (l’azienda del precedente esempio), c’è un’alternativa. In T.R.I.N.C.I. abbiamo costruito sul pilastro dell’identità sovrana un intero protocollo unico nel suo genere che prende il nome di 4RYA. Il nostro protocollo rappresenta in maniera completa ed esaustiva ciò che un’identità digitale sovrana deve offrire: l’utente può creare un’identità in totale autonomia, senza qualcuno che lo disintermedi. 4RYA, inoltre, permette di creare un’identità non solo assegnata ad esseri umani, ma anche a robot, a sistemi di identità digitale, a dispositivi IoT ed a tutto ciò che ad oggi nel panorama digitale collabora nella costruzione di un tessuto digitale.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato: 3. 4RYA





Come rendere la tecnologia Core e l’identità sovrana compatibile anche con le leggi?

Oggi si dà per scontato che fare un business consista nel farlo seguendo le leggi, ma la tecnologia blockchain generalmente non nasce in linea con le leggi, anzi, per determinati aspetti le blockchain non si preoccupano di quelle che sono regolamenti e leggi di uno Stato, proprio perché una blockchain si proclama generalmente sovrana. Le uniche leggi che vivono in una blockchain sono gli smart contract, quindi se l’utente “convince” lo smart contract a muovere del valore (per esempio denaro), lo smart contract lo muove.

Nei sistemi giuridici questo non può succedere: deve esserci un titolare di responsabilità nel poter eseguire determinate azioni. Quindi la tecnologia blockchain non nasce necessariamente in un contesto legale.

Ciò che è stato fatto con T.R.I.N.C.I. è stato costruire questa tecnologia blockchain attorno ad un pilastro di Legal & Compliance. Questo vuol dire che, se un’identità sovrana sulla tecnologia core produce e sviluppa una transazione con l’intento di trasferire dei valori (per esempio denaro) da un proprio wallet ad un altro wallet, questo intento può essere letto e decodificato fuori dalla blockchain (per esempio in un tribunale). Nel momento in cui si andrà quindi a sviscerare i contenuti della transazione (ove richiesto, per esempio in un tribunale) sarà molto chiaro quello che era l’intento dell’utente nel fare quella operazione. Il nostro impegno di costruire delle “transazioni parlanti”, quindi, ha come scopo principale il fatto di poter leggere chiaramente i dati delle transazioni anche fuori dalla blockchain, agevolando l’analisi delle stesse anche in ambiente legale.

Oggi possiamo dimostrare con una transazione fatta su T.R.I.N.C.I. che non c’è ambiguità nel contenuto. Questa è una sfumatura delicatissima; in altri protocolli come per esempio Bitcoin, se si analizza una transazione non è chiaro quello che è l’intento di chi l’ha sottomessa. Il core di bitcoin interpreta benissimo lo spostamento di denaro wallet to wallet, ma, esternamente alla blockchain, il documento che rappresenta la transazione non può essere preso in considerazione poiché al di fuori non ha valore e non ha significato.

Ecco perché nella tecnologia T.R.I.N.C.I. abbiamo costruito un protocollo dove le transazioni prodotte nel contesto della tecnologia T.R.I.N.C.I. hanno valore anche fuori da quel contesto. Ciascuna transazione produce in T.R.I.N.C.I. una marcatura digitale (come un documento) nel quale verrà automaticamente riportata una dicitura di questo tipo: “Io: il mio account ID. Destino a Giovanni: account ID di Giovanni. Questa transazione. Per questo pagamento. Per questa operazione. “

Così facendo, questa transazione farà sicuramente il suo percorso all’interno della blockchain, ma fuori dalla blockchain può essere letta e/o interpretata al pari di un contratto digitale firmato tra due soggetti.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato: 4. Legal & Compliance




2.1.4 Business: Circuito Synkrony All-In-One


2.1.4.1 Banking: Synkrony Payments


Il quarto pilastro che ci ha guidato nella costruzione di T.R.I.N.C.I. è legato all’obiettivo di agevolare il mondo del Business-Finance nell’ambito blockchain.

Questo perché la blockchain in generale ha pochissimi accessi verso i sistemi bancari e in molti casi scollegati tra loro, pertanto è spesso necessario saltare da una piattaforma all’altra per condurre operazioni ordinare.

Nella storia della blockchain in rapporto al mondo business sono stati proposti vari tentativi di connessione tra sistemi bancari e blockchain: ancora ad oggi, purtroppo, i due mondi non hanno beneficiato l’uno dell’altro a causa di tutta una serie di problematiche tecniche e burocratiche.

Ne è un esempio non solo l’ambiente b2b (Business-to-Business), ma anche quello del trading.

Tanto nel b2b ma soprattutto nel trading si riscontrano spesso difficoltà di interazione con i sistemi bancari a causa di compliance quasi inesistenti. La nostra soluzione si propone di risolvere il problema giuridico amministrativo offrendo ai trader (ed alle aziende) la possibilità di condurre tutte le proprie operazioni in un unico circuito.

Facciamo un esempio: quando un Trader decide di convertire in denaro i propri asset digitali ed inviare sul proprio conto bancario somme comprese tra i € 10.000,00 ed € 1.000.000,00 (o oltre), il bonifico che parte dall’ Exchange per giungere al Conto Corrente bancario dell’utente arriva spesso da paradisi fiscali o black listed come per esempio dal Belize, Isole Cayman Wyoming, Singapore (ed altri), per poi essere molto probabilmente messo in quarantena dalla banca di destinazione a causa di due fattori, il primo è la provenienza dei fondi da paradisi fiscali, il secondo è la scarsa o quasi totale assenza di competenze per eseguire le giuste pratiche di verifica e controllo: antiriciclaggio; anti terrorismo; mancanza di know-how relativo al mondo criptovalute; limiti massimali superati; altro.

A causa di queste problematiche può accadere che: nella migliore delle ipotesi l’utente faccia rientrare sul proprio wallet dell’Exchange i fondi; nella peggiore delle ipotesi i fondi rischiano di rimanere bloccati anche per mesi in attesa del via libera bancario. Il problema è “cross circuito” inteso circuito crypto - circuito banca: il circuito di un Exchange deve cioè interagire con il circuito bancario di una qualsiasi banca. Ecco dove risiede la difficoltà.

Per risolvere il problema abbiamo lavorato alla costruzione del circuito Synkrony, il quale, ospitando nativamente sia wallet cripto che wallet bancario, tiene traccia della provenienza dei fondi derivanti da cripto dall’inizio alla fine del suo ciclo e, contestualmente, produce apposita documentazione consentendo le adeguate verifiche necessarie e propedeutiche alla circolazione dei fondi senza problematiche burocratiche.

Il Circuito Synkrony Comprende: Synkrony Exchange è l’exchange per il mondo crypto; Synkrony Pay è il Pay Component dell’ecosistema, messo a disposizione degli esercenti (per vendere i propri prodotti e incassare moneta crypto), e degli utenti di base (per acquistare prodotti con le proprie crypto); Synkrony Payments è l’Internet Banking dove l’utente può aprire e gestire il proprio conto corrente V-IBAN.

Con Synkrony Payments l’utente (che sia trader, esercente o utente di base) ha a disposizione il proprio internet banking con: Conto “bancario”; V-IBAN dedicato; carta di debito Mastercard.

In Sintesi, un utente del circuito Synkrony avrà a disposizione tutti gli strumenti utili a: convertire denaro; trasferire denaro; effettuare pagamenti.

Come beneficio aggiuntivo, il Circuito Synkrony mette a disposizione dell’utente soluzioni personalizzate di gestione finanziaria con alti limiti di operabilità.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato: 7. Synkrony Payments




2.1.4.2 Exchange: Synkrony Exchange


Nel circuito Synkrony è di fondamentale importanza Synkrony Exchange, lo strumento che permette di coniugare tutta la tecnologia T.R.I.N.C.I. ed i propri protocolli nei confronti di quelle che sono le monete reali, quelle cioè che usiamo nella vita di tutti i giorni. Synkrony Exchange è nativo all’interno della tecnologia blockchain T.R.I.N.C.I. poiché è interamente e totalmente disintermediato tramite smart contract.

Synkrony Exchange permette, tramite particolari accordi bancari e particolari protocolli, di unire il mondo della moneta reale (Euro, Dollaro ecc..) al mondo di alta tecnologia blockchain (come Ethereum, Bitcoin) all’interno dello stesso terreno di gioco. Ecco che così si può produrre la massima aspirazione che ha guidato lo sviluppo di questa alta tecnologia fino ad oggi: quello di spostare Euro tramite una transazione fatta in blockchain.

Synkrony Exchange permette di: entrare in esso con monete di uso quotidiano (Euro, Dollaro eccetera); avere in cambio monete digitali che fanno il loro percorso nell’ambiente blockchain; monete digitali che un utente può convertire in Euro o Dollari (moneta FIAT) e depositare nel conto corrente all’interno del circuito Synkrony in modo veloce, sicuro e legale;

in maniera scherzosa lo abbiamo definito “sistema casinò”, che non ha a che fare con i giochi, bensì con il desk di ingresso al casinò: si arriva con gli euro, si cambiano in fiches; le fiches vengono usate per giocare ai tavoli; il giocatore vince/perde; torna al banco con le sue fiches perse/vinte; richiede il cambio in moneta Fiat; ottiene in cambio gli Euro (o altra moneta Fiat);

L’esempio appena fatto dà un’idea del sistema che abbiamo usato per permettere agli utenti, alle aziende, alle imprese, di utilizzare gli Euro (o altra Fiat) per entrare in questo mondo ed utilizzare il controvalore digitale che nel nostro caso si chiama Eurs per spostare valore e compiere delle azioni come ad esempio: comprare, fare acquisti; fare aste; proposte di acquisto; siglare dei contratti di compravendita;

Queste monete vengono quindi “smistate” secondo le regole definite dagli smart contracts. Infine, quando le monete arrivano al merchant, quest’ultimo può decidere di tornare su Synkrony Exchange e riconvertire nelle monete che gli spettano.

Tutto ciò, per noi in Affidaty, è un punto fondamentale che non può prescindere dall’essere una cosa necessaria per produrre oggi una tecnologia blockchain che sia al passo con i tempi e con i fatti.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato: 5. Synkrony Exchange




2.1.4.3 Pay Component: Synkrony Pay


Altra tematica calda è il mondo Payment in Crypto: se l’utente effettua un pagamento in cripto, oggi, deve necessariamente cambiare del denaro; questo perché non esistono gli strumenti in linea con le normative europee atti a consentire pagamenti in cripto verso un esercente, per esempio attraverso un POS.

Attraverso il Circuito Synkrony, un trader che opera sui principali Exchange, può inviare cripto direttamente dal suo account al conto del merchant che ospita il nostro Pay Component, oppure può aprire un wallet Synkrony ed effettuare pagamenti o trasferimenti anche di piccole somme senza la necessità di disinvestire e convertire grandi somme.

Il Pay Component di Synkrony permette all’utente di pagare un prodotto direttamente con le proprie cryprovalute, diversamente dalla quasi totalità dei sistemi odierni: questi, infatti, permettono all’utente solo di effettuare un cambio “al volo” delle proprie crypto in moneta FIAT che poi vanno all’esercente per l’acquisto del prodotto.

Tramite il Pay Component, invece, l’utente che effettua l’acquisto compie il pagamento con le proprie crypto; all’esercente arrivano le crypto pure; quest’ultimo, poi, potrà se vorrà, tenerle sul proprio wallet o scaricarle, cambiandole in moneta FIAT sul suo conto corrente in Synkrony Payments.

Per maggiori approfondimenti è possibile consultare il capitolo dedicato: 6. Synkrony Pay Component




2.1.4.4 Crypto Esercente


L’ ecosistema Synkrony risolve implicitamente il terzo problema: “Ma io come posso ora usare i Bitcoin che ho incassato? Devo essere comunque in grado di pagare bollette, stipendi dei miei dipendenti e quant’altro”.

Questa è la domanda di maggiore impatto per l’esercente; questo è il problema maggiore di cui l’esercente non deve soffrire.

Synkrony Exchange è dotato dello strumento che risolve questo problema: l'Instant Change, infatti, permette all'esercente di cambiare immediatamente (se attivato) i propri Bitcoin in moneta FIAT.

Grazie all'Instant Change gli esercenti potranno quindi avere la giusta confidenza nel trasformare i propri Bitcoin in moneta di uso corrente (FIAT).

Grazie alla continua connessione tra Synkrony Exchange, Synkrony Pay e Synkrony Payments, infatti, l’esercente ha ora in mano tutti gli strumenti per: accedere al mercato di utenti possessori di crypto che vogliono pagare prodotti/servizi con le proprie crypto; accettare pagamenti in crypto; incassare velocemente grazie al Pay Component; tenere sul proprio wallet Synkrony Exchange le crypto incassate; vendere le crypto incassate sul mercato, direttamente ad un utente interessato, grazie all’orderbook presente nell’ecosistema Synkrony; scaricare le crypto, convertendole in denaro FIAT, inviando il denaro al proprio conto corrente in Synkrony Payments.




2.1.4.5 Crypto - DeFi


Il reperimento di Cryptovalute da immettere nel proprio mercato è una tematica di costante interesse per qualsiasi Exchange.

Gli Exchange, infatti, effettuano spesso acquisti di grandi quantità di Cryptovalute (da altri Exchange o da grosse "balene") da immettere nel proprio mercato a disposizione degli utenti.

Attraverso l’ecosistema Synkrony, abbiamo voluto snellire e velocizzare il reperimento di criptovalute affrontando il problema in modo innovativo rispetto alla concorrenza. Synkrony Pay Component è lo strumento grazie al quale viene creata la disponibilità di valute crypto: sia all’interno di Synkrony Exchange per permettere agli utenti di acquistare e vendere cripto da/a Synkrony Exchange; sia direttamente a disposizione degli utenti in modo disintermediato tramite lo strumento orderbook: quest’ultimo, infatti, mette in diretto contatto acquirente e compratore, senza intermediazione, permettendo lo scambio diretto tra i due utenti.

Ecco che Synkrony Exchange si presenta in questo modo come puro DeFi.

In questo modo saranno gli utenti stessi che, attraverso il Pay Component, daranno vita all’economia circolare che permetterà di generare l’accumulo e lo scambio di criptovalute attraverso Synkrony Exchange per utenti trader, esercenti ed utenti di base.

Così facendo si vanno a racchiudere in un unico sistema 4 passaggi fondamentali che permettono all’ecosistema di auto alimentarsi: recuperare le cripto direttamente dal mercato: gli utenti possono cambiare le proprie cripto con denaro FIAT vendendole a Synkrony e ricevendo denaro Fiat in cambio; recuperare le cripto risolvendo un problema reale, offrendo cioè un Pay Component che permette all’utente che vende di incassare direttamente dall’utente che compra tramite l’orderbook; permettere sia all’esercente che al trader che operano sul circuito Synkrony di avere accesso ad un sistema bancario a norma con le direttive UE, ma allo stesso tempo che non crea ostacoli ingiustificati alle transazioni e che non dà impedimenti di cambi e di trasferimenti di denaro; La tecnologia T.R.I.N.C.I., attraverso le HDSB (High Density Scoped Blockchain), permette di sincronizzare tecnologie diverse come Ethereum, Bitcoin, Dash, tutti i protocolli maggiormente conosciuti: questo porta agli utenti sicurezza di uso dei preferiti asset/token/cryptovaluta all’interno dell’ecosistema.




2.1.4.6 Listing


Ad oggi il processo di listing in un qualsiasi Exchange risulta complesso.

Esistono Exchange che non permettono il listing di monete che sono sconosciute o che non seguono i dettami minimi di capitalizzazione di mercato (filtri di accesso molto stretti).

D’altro canto, alcuni Exchange permettono il listing di qualsiasi token, amplificando quindi il problema “Scam-Coin” causato da un filtro di accesso troppo blando.

L’ecosistema Synkrony permette, in modo snello ma attento, ad un soggetto di introdurre un nuovo token piuttosto rapidamente, ma al tempo stesso di non evitare ad un utente il problema di entrare in un circuito contenente soggetti/token che potrebbero sminuire il proprio progetto, come per esempio token scam.

Tutto ciò senza costringere l’utente creatore del token a creare una capitalizzazione di mercato per introdurre un nuovo token.

Gli utenti che decideranno di acquistare token quotati e listati su Synkrony Exchange, avranno a disposizione token quotati e listati da imprenditori seri, vigilati da Affidaty: questo permetterà agli utenti che acquisteranno token di avere una garanzia sul fatto che coloro che hanno listato token sono imprese che hanno progetti seri, validi e potenzialmente realizzabili.

Questo è possibile grazie all'ingegneria di un processo che prende il nome di Witness, cioè la testimonianza dell’avvenuto. Se, per esempio, all’interno di una moneta quotata viene affermato che esiste un sottostante in opere d’arte, abbiamo la prova che queste opere d’arte sono state acquistate grazie alla Witness, cioè il pagamento effettuato sempre all’interno del nostro sistema: Synkrony + Synkrony Pay + Esercente che vende l’opera.

L’opera, oltre ad avere il pagamento tracciato, ottiene anche il proprio tracciamento all’interno dei sistemi Synkrony tramite un hash che determina quale genere di opera è stata acquistata, a quale ora ed a quale prezzo.

Questo vale non solo per opere d’arte, ma per qualsiasi bene.

Chiaramente queste sono le garanzie a livello tecnologico offerte dal sistema. Esistono anche garanzie a livello umano, come per esempio l’analisi di un Business Plan, di Funzionalità Progettuale, Studio di Fattibilità eccetera. Queste sono analisi interne effettuate dal team di Affidaty nei confronti di qualsiasi progetto di tokenizzazione.

2.2 - Tecnologie scelte


2.2.1 Blockchain pura, non proveniente da fork di altre tecnologie.


T.R.I.N.C.I. non è un fork di un’altra blockchain. Né di bitcoin, né di Ethereum, né di Polkadot o altre. T.R.I.N.C.I. è una blockchain nata da zero.

La motivazione principale che ci ha spinto a costruire una blockchain non derivante da fork è relativa al fatto che volessimo essere una nuova proposta differente dalle tecnologie già presenti sul mercato.

Il nostro obiettivo è quello di produrre una tecnologia …




2.2.2 Rust e Web Assembly


Abbiamo fatto molti tentativi in vari linguaggi di scrittura: C#, Java, Go (uno dei candidati più importanti per la stesura della tecnologia).

Dai giganti si impara in fretta che una tecnologia la si sceglie su due filoni principali: 1 - la conoscenza che i propri sviluppatori hanno di una tecnologia particolare ti spinge a fare scelte importanti verso di essa; 2 - testare le tecnologie ed i linguaggi direttamente sul campo e non semplicemente consultando Stack Overflow per capire come performano, poiché ogni linguaggio ha delle caratteristiche che si vedono nell’ambito della propria applicazione, non a livello generale.

Abbiamo quindi costruito un classico banco di prova per testare quale tecnologia, quale linguaggio fosse più attinente ai nostri scopi.

Quando abbiamo messo sul banco di prova la nostra applicazione, i nostri sistemi, i nostri algoritmi, le nostre funzioni, abbiamo effettuato benchmark mirati per misurare il consumo di memoria e l'utilizzo della CPU, così da avere un metro di paragone tra i vari linguaggi in un contesto blockchain.

Tra queste, sviluppate in Rust, C Sharp o Go, il linguaggio Rust è risultato il migliore, staccando di un ordine di grandezza tutti gli altri linguaggi scelti.




2.2.3 Rust


Rust è un linguaggio compilato a basso livello con tipizzazione statica, multi-paradigmico, che nasce con l’intento di primeggiare in termini di sicurezza e di prestazioni. Rust nasce nel 2010 nei laboratori Mozilla Research, ad oggi è uno dei linguaggi più amati dagli sviluppatori (stackoverflow survey) e vanta di grandi community che lo promuovono, offrono assistenza e sviluppano moduli e documentazione per il suo ecosistema. Le ragioni del suo successo ed i motivi per cui è stato scelto come linguaggio di sviluppo del nodo della rete blockchain T.R.I.N.C.I. sono svariate: alte prestazioni assicurando comunque memory safety, buon supporto della programmazione concorrente, grossa crescita di librerie secondarie, retrocompatibilità con versioni precedenti del linguaggio.

C’è però da constatare che per garantire la memory safety di cui si fa vanto, il linguaggio è molto rigido per quanto riguarda regole di scrittura del codice. Per questo motivo entra in gioco il Package Manager di Rust, Cargo, che si occupa anche di compilare.

Cargo, infatti: offre, in ambito di compilazione, una dettagliata collezione di messaggi per guidare lo sviluppatore a risolvere gli errori che comprometterebbero la sicurezza del pacchetto creato; vanta ottimi strumenti di gestione di dipendenze, versionamento di queste e distribuzione di pacchetti generati dalla community; rende impeccabile l’interazione con pacchetti terzi, portando lo sviluppatore a concentrarsi semplicemente all’implementazione e non a problemi di compatibilità che un pacchetto potrebbe causare in caso di aggiornamenti non attesi.

Rust è stato scelto come linguaggio di programmazione poiché ritenuto maggiormente idoneo per sviluppare T.R.I.N.C.I., ma è necessario comprendere che la competenza di sviluppatore in Rust è strettamente dedicata alla tecnologia del core e del nodo per modificarne l’uso. Ecco perché, per un’azienda che decide di usare e/o di implementare la tecnologia T.R.I.N.C.I. nel proprio business, non è strettamente necessario avere uno o più sviluppatori con conoscenza di Rust. Diventerà necessario solo qualora l’azienda avesse interesse a modificare il core o il nodo per farci un altro uso.




2.2.4 WASM (WebAssembly)


Il secondo pilastro su cui si basa la nostra tecnologia è il WASM, prodotto di una delle community W3C. Questo è un formato binario di istruzioni per virtual machine stack-oriented. L’obiettivo del WASM è quello di avere come prodotto della compilazione di codice sorgente un target file che possa essere eseguito via web da applicazioni client e server.

La forza del WASM quindi è la sua portabilità, potendolo eseguire sui web browser più comuni (Firefox, Chrome, Safari e Edge), ed elasticità dato che è possibile generare file WebAssembly dai linguaggi di programmazione più comuni, degni di nota sono: C, Ruby, Go e Rust essendo così effettivamente un “esperanto” per prodotti web. I punti di forza del WebAssembly sono: Efficienza e velocità: lo stack machine WASM è progettato per essere codificato in un formato binario efficiente in termini di dimensioni e tempi di caricamento. WebAssembly mira a essere eseguito a velocità nativa sfruttando le capacità hardware comuni disponibili su un'ampia gamma di piattaforme; Sicuro: WebAssembly descrive un ambiente di esecuzione sandbox, sicuro per la memoria. Quando è incorporato nel Web, WebAssembly applica i criteri di sicurezza same-origin e di autorizzazione del browser; Open e Debuggable: WebAssembly è progettato per essere stampato in un formato testuale per il debug, il test, la sperimentazione, l'ottimizzazione, l'apprendimento, l'insegnamento e la scrittura di programmi. Il formato testuale è utilizzato inoltre quando si visualizza il sorgente dei moduli Wasm sul web; Parte della piattaforma open web: WebAssembly è progettato per mantenere la natura versionless, feature-tested e retrocompatibile del Web. I moduli WebAssembly saranno in grado di chiamare dentro e fuori dal contesto JavaScript e di accedere alle funzionalità del browser attraverso le stesse API Web accessibili da JavaScript. WebAssembly supporta anche incorporazioni non Web.

ll WebAssembly, all’interno di T.R.I.N.C.I., è il formato nel quale gli smart contract sono esportati. Essendo la produzione di questi una delle attività più frequenti e comuni all’interno di Affidaty (oltre ad essere il mezzo necessario alla community per sfruttare la blockchain T.R.I.N.C.I. nel prossimo futuro), abbiamo deciso di scegliere una tecnologia che fosse il più possibile versatile, di facile adozione per un utente più o meno esperto, e non vincolante nell’utilizzo di un linguaggio piuttosto che di un altro, poiché: Lo sviluppo degli smart contracts è una attività molto più quotidiana rispetto allo sviluppo del core. La tecnologia di base, una volta sviluppata, non viene alterata a meno di inserimento di grosse major release.

Combinando i moduli Rust sfruttati dai nodi della blockchain e il WebAssembly è possibile creare strumenti di simulazione e test che possano essere eseguiti agevolmente in contesti WebApp. Grazie a ciò un utente può: creare una transazione, verificare la sua validità, simulare la sua esecuzione, valutare il suo esito, infine una volta soddisfatto, l’utente ha la possibilità di sottomettere nella rete di produzione l'effettiva transazione, conoscendo già il suo esito.

Questo è solo un esempio delle possibili applicazioni degli strumenti a nostra disposizione, che combinati con le soluzioni da noi implementate, sinergicamente comportano lo sviluppo di un ecosistema completo e trasparente rispetto alla rete T.R.I.N.C.I. rendendo la blockchain, spesso complessa ad occhi esterni, un mezzo di facile accesso.




v2.2.5 Cross platform.


Cross device, subito testabile.

Nell’ambiente blockchain Metamask è un tool di riferimento, un plugin che permette l’utilizzo di wallet di Ethereum all’interno dei comuni browser. Sottolineiamo: è un plugin da installare, con tutte le eventuali difficoltà che ciò può comportare.

Molte persone, d’altro canto, non usano Metamask: quando un utente si trova all’interno di portali come OpenSea o altri, scopre in quel momento che serve un Metamask perché potrebbe avere i propri Ethereum su Binance o Coinbase o altri exchange.

Quando l’utente vorrà usare i propri Ethereum dovrà necessariamente installare un plugin.

Con T.R.I.N.C.I. abbiamo riscritto tutta la tecnologia in puro Javascript.

Quindi, per utilizzare la tecnologia client, usare il wallet, o la Identità Sovrana di T.R.I.N.C.I. (4RYA) non è necessario installare alcun plugin: è sufficiente usare un comune browser o una app mobile per poter usare un componente che abbiamo chiamato T2Lib per fruire di tutte le caratteristiche di produzione di transazioni, deleghe e tutte le caratteristiche che sono all’interno della tecnologia blockchain, direttamente dal browser.

L’utente, quindi, si trova a poter usare questa tecnologia con la stessa facilità d’uso di un popup o di una normale finestra html in cui interagisce, ma dietro c’è tutta una tecnologia di crittografia avanzata che permette: all’utente di usare il proprio wallet in totale sicurezza, perché persino chi integra questa tecnologia non sarà mai in grado di vedere, compromettere, corrompere la chiave privata per sottrarre informazioni; una trasparenza del codice di sviluppo in quanto l’applicazione è open source. La tecnica crittografica è quindi chiaramente dichiarata, mostrando che non sono stati usati sistemi basati su cookie o artifici diversi.




2.2.6 User Experience curata.


Il nostro team dedicato di UX lavora costantemente per ridurre la barriera di utilizzo di questa tecnologia, perché in molti non hanno ancora compreso cosa vuol dire avere a che fare con un wallet.

Da una parte c’è una linea di business che richiede costantemente di rendere più banale possibile l’utilizzo degli strumenti; mentre dall’altra parte ci siamo messi noi delle barriere da non superare, degli auto limiti che ci siamo imposti affinché gli strumenti che mettiamo a disposizione dell’utente vengano utilizzati con la corretta attenzione.

Al contempo abbiamo cercato di introdurre una fase di formazione sul campo, dove l’utente, mano a mano che utilizza gli strumenti di T.R.I.N.C.I. come la T2Lib, l’Authin, il Pay Component, viene informato durante lo sviluppo del processo.

Quindi, per esempio, durante la creazione di un wallet, informiamo l’utente di ciò che gradualmente sta accadendo sul suo schermo per dargli coscienza di ciò che sta facendo. Vogliamo dare agli utenti la percezione del valore che stanno ricevendo, senza ridurre tutto a dei semplici click.

Tramite processi di UX design specifici, mettiamo in condizione l’utente di ricevere informazioni in real time mentre compie azioni sui nostri portali; questo con l’obiettivo di portarlo ad una consapevolezza ed una confidenza crescenti mentre esplora l’ecosistema nel quale sta ponendo la propria fiducia.

Quindi: da una parte regaliamo tanti piccoli tips, che rendono lo sviluppatore confidente della tecnologia e subito in grado di vedere i risultati di ciò che sta programmando; dall’altra, per l’utente classico, portiamo la semplicità d’uso, senza vedere la complessità del sistema, raggiungendo l’obiettivo sul monitor (o su un qualsiasi altro device) con una fluida e semplice UX.

3.1 Introduzione


Applicare l'ecosistema blockchain nel mondo degli affari richiede che le transazioni non siano anonime e che l'identità digitale sia sovrana, cioè costruita dagli utenti in primis e resa più valida da altre identità autorevoli grazie ai certificati digitali, sul modello di Certification Authority. Secondo questo principio, l'uomo non è l'unico in grado di possedere un'identità digitale, ma lo sono anche i dispositivi IoT, i software, i robot e tutti quei sistemi in grado di firmare digitalmente.

Una firma digitale dovrebbe inizialmente basarsi su protocolli già conosciuti e accademicamente validi (ECDSA, RSA, ecc.), ma dovrebbe lasciare spazio anche ad innovazioni crittografiche: questo anche in vista dell'era quantistica che metterà seriamente in discussione l'integrità del digitale, delle firme basate su curve ellittiche e non solo. Ogni utente deve conservare la propria chiave privata; quest’ultima non deve essere mai trasferita a sistemi di terze parti.

L'utente deve qualificarsi con la propria chiave pubblica in blockchain. Successivamente, gli utenti possono utilizzare la loro chiave privata per firmare ogni transazione da inviare alla blockchain. Tale operazione, che non può essere eseguita da nessun altro utente (poiché nessuno conosce la chiave privata di altri utenti), acquista validità legale. Le identità digitali di qualsiasi soggetto che utilizza questa metodologia sono contenute all'interno della blockchain T.R.I.N.C.I® per consentire all'intero ecosistema di utenti, aziende, robot e dispositivi IoT di durare per sempre, affidando all'utente la governance dei dati per tutta la vita.

3.2 Cos’è 4RYA


4RYA (piattaforma raggiungibile navigando la home page al link https://4rya.io/) è uno dei pilastri sui quali è nata la tecnologia T.R.I.N.C.I.

4RYA_1

4RYA_2

In blockchain un wallet può contenere denaro; l’indirizzo di un wallet coincide con la chiave pubblica generata dal processo di creazione di identità digitale.

Per essere più chiari si fa ricorso ai concetti di chiave pubblica e privata: T.R.I.N.C.I. supporta molti tipi di algoritmi di firma, il principale è ECDSA su curva P384 che fondamentalmente crea una coppia di chiavi, una pubblica ed una privata.

La chiave pubblica diventa automaticamente l’indirizzo del wallet. Per esattezza la sua versione compressa, solo per una questione di performance: data la chiave pubblica esiste un processo deterministico irreversibile che fa ricavare l’account ID.

La chiave privata consente all’utente di manifestare la propria volontà di fare azioni, quindi consente di usarla proprio come firma.

Quindi, paradossalmente, qualunque coppia di chiavi pubblica e privata può essere considerata come un account attendibile. Questo vuol dire che non c’è bisogno di pre registrare account, tant’è vero che non c’è un processo di creazione di una utenza: si utilizza una “Convention over Configuration” dove si dice che esistono già tutti gli wallet all’interno della blockchain.

Questo non va confuso con il fatto che il database sia già pre riempito con tutti gli wallet. Questo vuol dire che se si chiede ad un nodo qual è il balance di un wallet che non ha mai visto, questo non risponde dicendo che non lo ha mai visto, bensì che quel wallet ha balance zero. Quindi per il nodo il balance esiste, ma non lo ha ancora salvato poiché non ha mai avuto modo di salvare alcun dato o transazione di quel wallet.

Questo passo è stato molto importante, poiché è stata una decisione che ci ha poi permesso di sviluppare tante caratteristiche che hanno come base questo concetto.

Applichiamo questo concetto del “Convention over Configuration” all’identità digitale: creando una ID sul proprio computer, questa è come se fosse sempre esistita dall’altra parte; l’utente può inviare dei fondi, del denaro, dei dati; la tecnologia T.R.I.N.C.I. si farà carico di salvarli all’interno degli spazi di memoria dedicati.

  • Quindi, 4RYA che cos’è? 4RYA è un protocollo, ma è anche uno smart contract ed un modo di concepire l’identità. Le identità di 4RYA sono tutti account, quindi coppie di chiavi pubblica e privata capaci di firmare, ad eccezione dei Soulless Account.

In questa anagrafe digitale, infatti, c’è spazio sia per gli utenti “attivi” (cioè capaci di produrre firme digitali sulle varie curve crittografiche note), sia per i Soulless Account, cioè account senza anima: questi Soulless Account rappresentano oggi la maggior parte degli account che sono presenti all’interno della nostra tecnologia: NFT, wallet di una organizzazione, un qualsiasi wallet che dall’esterno non ha un soggetto fisico che possa firmare in nome e per conto del wallet, ma c’è uno smart contract che governa le regole con cui questo wallet si esprime.

3.3 IoT


È un argomento seguito dalla tecnologia T.R.I.N.C.I. Esso rientra nel segmento di 4RYA, ma fra gli utenti di tipologia “Attivi”.

Nei dispositivi IoT oggi prodotti è comune trovare un modulo TPM. Quest’ultimo nasce con una coppia di chiavi crittografiche univoche, che dunque identificano il dispositivo che ospita il modulo. In aggiunta, le chiavi in questione non sono accessibili dall'esterno, quindi non è possibile sottrarre e subire attacchi "MITM", dove il malintenzionato intende identificare il dispositivo in questione. Ad oggi l'utilizzo del modulo è molto diffuso, un esempio su tutti è Windows 11 che necessita come componenti minime per l'avvio del sistema operativo un modulo TPM.

Questo chip ha una caratteristica peculiare: se esso contenesse la coppia di chiavi pubbliche e private, ma la chiave privata non fosse visibile, non sarebbe asportabile poiché non è in una zona di memoria del chip disponibile all’esterno; qualsiasi tentativo di forzatura del chip, anche la sola forzatura di disconnessione del chip, distruggerebbe il suo contenuto. È un modo sicuro poiché se io creo un chip con una chiave, questo chip, finché rimane ancorato al computer, è in grado di produrre firme. Nessuno può leggere la chiave privata del modulo poiché non è disponibile; se un utente provasse a rimuovere il chip per ispezionarlo con strumenti elettronici esterni ed andare a vedere quello che è scritto nella EPROM, dovrebbe fisicamente dissaldarlo, compromettendolo. In questo modo, l’utente non sarebbe più in grado di leggerne il contenuto.

Il modulo TPM è lo strumento che permette ai dispositivi IoT di interfacciarsi con 4RYA, permettendogli di firmare transazioni qualora ce ne sia bisogno.

3.4 Sistema Business oriented applicato ad 4RYA.


Nel definire e spiegare T.R.I.N.C.I. spesso parliamo di “tecnologia business oriented”, cioè di un sistema non solo costruito attorno all’utente business (B2B), ma anche per utenti consumer (B2C). Come 4RYA interviene in tutto questo?

4RYA è pensato per gestire tutta la catena della Certification Authority tramite l’utilizzo di certificati e di deleghe.




3.4.1 Certificati.


I certificati hanno pregi e difetti. Il primo pregio è che l’utente è in grado di produrre un documento che indipendentemente dal contesto (quindi anche offline) può dimostrare che una certa chiave pubblica, un certo soggetto ritenuto verosimilmente autorevole, ha certificato una serie di informazioni.

Per esempio, nel caso dell’identità digitale (carta d’identità), un Ente certifica le generalità di un cittadino (la data di nascita, la residenza, nome e cognome). Il problema è che questo documento ha valore solo se le informazioni fornite sono integrali. L’utente è quindi costretto a fornire tutte le informazioni del documento anche in contesti in cui una sua visione parziale sarebbe sufficiente all’ottenimento della verifica.

In T.R.I.N.C.I. abbiamo risolto questo problema costruendo certificati più sofisticati che fanno uso dei Merkle tree e tutta una serie di crittografie di ultima generazione dove si può produrre un sottoinsieme del certificato che ne mantiene la validità complessiva.

Esempio: se un Comunne certifica i dati per interi di un soggetto in un certificato, egli può estrarre da tale certificato un “sotto-certificato” che certifichi solamente la propria data di nascita; così il soggetto può spendere questo certificato (“sotto-certificato”) senza essere costretto a fornire la totalità dei propri dati (per esempio per proteggere la propria privacy).




3.4.2 Deleghe


Quando si affrontano seriamente le difficoltà di classe Enterprise, ponendosi nei panni delle aziende che devono utilizzare determinate tecnologie, balzano subito all’occhio una serie di problematiche:

  • Chi tiene la chiave privata dell’azienda;
  • Chi sono i responsabili dell’azienda;
  • Cosa possono fare;
  • Che mansioni hanno;
  • Che deleghe hanno;

In ambiente blockchain queste situazioni non sono mai state prese in considerazione. Semplicemente: “c’è un wallet, chi ha la chiave privata opera.”.

Nel mondo reale, in aziende reali (come la stessa Affidaty S.p.A) è molto difficile gestire tutto in questo modo.

  • Innanzitutto la chiave privata una volta che è stata conferita a qualcuno non può più essere chiesta indietro perché la persona potrebbe essersi creata una copia;
  • Inoltre, non si può cambiare la chiave privata: non è come una password che si può gestire e modificare facilmente. Se un’azienda affida ad un proprio dipendente la gestione di una chiave privata ed un domani quel dipendente se ne andasse per qualsiasi motivo, egli continuerà ad avere una copia della chiave privata; non potrebbe essergli chiesto di modificarla o di mostrare che l’abbia distrutta;

Chi ha la chiave privata, oggi, fa tutto. Diversamente, Affidaty ha costruito in T.R.I.N.C.I. un sistema di Deleghe in cui un account che ha la sua chiave privata può costruire delle deleghe specifiche per una serie di utenti in modo tale che:

  • se è l’Utente 1 ad utilizzare la delega per firmare quella transazione, rimarrà traccia nella blockchain che quel consenso è stato dato da lui. Non la chiave privata originale, ma quella delegata dell’Utente 1;
  • questa cosa non può esser fatta con il sistema classico, condividendo la chiave: l’azienda condivide la chiave con 5 soggetti, per la blockchain è sempre un soggetto unico che opera, quindi non si può distinguere se quell’azione l’abbia fatta uno piuttosto che un altro;
  • con le deleghe, invece, si inizia ad avere un’esperienza concreta nella distribuzione dei ruoli e dei compiti all’interno di uno smart contract;
  • inoltre, si possono confinare quelle che sono le attività possibili all’interno di una delega stessa. La delega è un certificato in cui può essere scritto che un Utente 1 delega un altro Utente 2 per effettuare trasferimento di denaro con determinati limiti ed in certe condizioni;
  • questa delega può essere persino revocata. In blockchain, paradossalmente, non si revoca nulla, non si distrugge nulla, neanche nella blockchain di T.R.I.N.C.I. è possibile farlo, ma si può aggiungere un’informazione che invalida l’informazione precedente;
  • quindi, tecnicamente, se un utente avesse fatto una delega ad un altro utente, colui che ha prodotto una delega può produrre una contro delega che va ad annullare quella precedente, per cui: nel momento in cui l’utente va a spendere la sua delega, c’è un sistema all’interno del core che controlla se qualcuno non l’abbia invalidata prima di spenderla;
  • ecco che si può costruire un sistema anche temporaneo per far sì che un’azienda possa delegare un dipendente o un reparto amministrativo per operare su un wallet.
  • in questo modo, se un dipendente va via dall’azienda (per qualsiasi motivo) il sistema: revoca la delega; - la chiave privata rimane sempre al suo posto; - viene prodotta una delega per un altro utente; - in questo modo il sistema continua a funzionare senza dover distruggere o conservare la chiave privata in modo fantasioso.

4.1 Normativa di riferimento


Affidaty S.p.A. è conforme alle normative vigenti in materia di contrasto al riciclaggio di denaro e al finanziamento del terrorismo, agli standard europei in tema di privacy e data protection (Regolamento UE 2016/679 - GDPR), nonchè in linea con il Decreto del Ministero dell’Economia e della Finanza del 13 gennaio 2022 concernente le modalità e le tempistiche con cui i prestatori di servizi relativi all’utilizzo di valuta virtuale e i prestatori di servizi di portafoglio digitale sono tenuti a comunicare la propria operatività sul territorio nazionale.

Dalla data del 29/07/2022 Affidaty S.p.A. è ufficialmente iscritta con il numero PSV57 alla sezione speciale del registro dei cambiavalute (prestatori di servizi relativi all’utilizzo di valuta virtuale) presso l’Organismo per gli Agenti Mediatori (OAM), in conformità all’obbligo previsto dal Decreto del MEF del 13/01/2022 (https://www.organismo-am.it/elenchi-registri/operatori_valute_virtuali/).

Pertanto Affidaty S.p.A. è in piena conformità per lo svolgimento della seguente attività: Prestatore di servizi relativi all’utilizzo di valuta virtuale e delle seguenti tipologie di servizio:

  • Servizi funzionali all’utilizzo e allo scambio di valute virtuali e/o alla loro conversione da ovvero in valute aventi corso legale o in rappresentazioni digitali di valore, ivi comprese quelle convertibili in altre valute virtuali;
  • Servizi di emissione, offerta di valute virtuali;
  • Servizi trasferimento e compensazione in valute virtuali;
  • Ogni altro servizio funzionale all'acquisizione, alla negoziazione o all'intermediazione nello scambio di valute virtuali (es. esecuzione, ricezione, trasmissione di ordini relativi a valute virtuali per conto di terze parti, servizi di collocamento di valute virtuali, servizi di consulenza su valute virtuali)

Ai sensi del d.lgs n. 231 del 21 novembre 2007, in attuazione della direttiva 2005/60/CE concernente la prevenzione dell'utilizzo del sistema finanziario a scopo di riciclaggio dei proventi di attività criminose e di finanziamento del terrorismo nonché della direttiva 2006/70/CE che ne reca misure di esecuzione, Affidaty S.p.A. rispetta gli obblighi di adeguata verifica e di verifica rafforzata della clientela, gli obblighi di registrazione delle informazioni acquisite nelle suddette verifiche e gli obblighi di segnalazione di operazione sospetta.

Normativa di riferimento DECRETO LEGISLATIVO 21 novembre 2007, n. 231 https://www.gazzettaufficiale.it/eli/id/2007/12/14/007X0246/sg

Ministero dell’Economia e delle Finanze - Decreto del 13 gennaio 2022 https://www.gazzettaufficiale.it/eli/id/2022/02/17/22A01127/sg

Regolamento (UE) 2016/679 del Parlamento europeo e del Consiglio, del 27 aprile 2016, relativo alla protezione delle persone fisiche con riguardo al trattamento dei dati personali, nonché alla libera circolazione di tali dati e che abroga la direttiva 95/46/CE (regolamento generale sulla protezione dei dati) (Testo rilevante ai fini del SEE) https://eur-lex.europa.eu/legal-content/IT/TXT/?uri=uriserv:OJ.L_.2016.119.01.0001.01.ITA&toc=OJ:L:2016:119:TOC

5.1 Exchange nativo, FIAT friendly.  




SynkronyExchange_1



L'intero ecosistema blockchain è stato pensato fin dall'inizio con un Exchange progettato per funzionare all'interno di T.R.I.N.C.I. 2.0: Synkrony Exchange. Si tratta di un portale che permette la disintermediazione delle monete all’interno della tecnologia T.R.I.N.C.I. e fuori da essa.

Synkrony Exchange è costruito per ospitare:
stablecoin peggate a monete FIAT; cryptovalute più conosciute, come Bitcoin, Ethereum, Dash, Litecoin, Dodgecoin; asset dedicati a circuiti a spendibilità limitata e creati su T.R.I.N.C.I.® 2: criptovalute; NFT.

Tutto questo è stato creato per agevolare il business e le aziende.

Le monete che vengono ospitate nell’ecosistema T.R.I.N.C.I. possono essere scambiate tramite l'Order Book, uno strumento sviluppato da Affidaty e situato sulla nostra piattaforma di scambio Synkrony Exchange.

La piattaforma è gestita dal relativo smart contract che permette di scambiare criptovalute e moneta FIAT, rendendo possibile l’interazione con blockchain esterne come (Bitcoin, Ethereum, eccetera), così da permettere uno scambio disintermediato tra coni sia esterni (esempio Bitcoin, Ethereum, eccetera) che nativi in T.R.I.N.C.I.. L’obiettivo è quello di allargare il più possibile la cerchia di monete esterne, pur scegliendo le sole solide ed affidabili.

Synkrony Exchange è DeFi, quindi assolutamente decentralizzato.

I punti focali di Synkrony Exchange sono:

  • Legal/Compliance
  • Performance & Stability focused
  • Stable Coin Oriented
  • B2B
  • Supporto ad aziende, integratori, developer di alto profilo/gold developer/sviluppatori alle prime armi"

Di fondamentale importanza è che garantisce il servizio di conversione Euro <-> Token.

Ogni processo è governato da uno smart contract all'interno della blockchain T.R.I.N.C.I, coinvolge token specifici presenti all'interno della blockchain stessa e non le classiche monete FIAT (Euro, Dollaro, ecc...).

Per facilitare l'utilizzo di questi token in favore degli utenti che non sono avvezzi alla compravendita di queste monete, è stato realizzato un servizio dedicato, che offre un flusso di pagamento integrato (il Synkrony Pay Component che approfondiremo nel capitolo 6) che consente agli utenti stessi, in pochi step, di acquistare i token necessari all'operazione mediante Carta di Credito o bonifico bancario, senza interrompere il flusso di lavoro pensato sulle piattaforme in cui si fa uso del token stesso.

Questo servizio viene erogato da Synkrony Exchange ed è deputato a servire la specifica HDSB, nel rispetto delle leggi vigenti in materia, sia di cambiare gli importi da Euro a Token, che l'operazione inversa, in modo da retrocedere i proventi del servizio offerto dall'azienda ai relativi Stakeholder direttamente in valuta FIAT.

In estrema sintesi gli utenti cambiano FIAT in Token, spendono token nei servizi presenti all'interno di una specifica HDSB, i Token si muovono secondo la programmazione prevista nei token stessi, i beneficiari dei token li cambiano in moneta FIAT.

Sistema di monete in Synkrony Exchange

6.1 Cos'è Synkrony Pay Component




PayComponent_1



Synkrony Pay è uno strumento di pagamento DeFi che consente ad ogni negozio fisico o e-commerce di incassare crypto in modo decentralizzato e valuta FIAT nel circuito SEPA, in totale sicurezza e nel rispetto delle normative vigenti.

Una delle attitudini classiche di chi gestisce crypto è quella di fare Holder: cioè quella di conservare i denari per far sì che questi, se “annaffiati” bene, aumentino di valore. Le cose in realtà non stanno sempre così: per far acquisire valore generalmente si deve aumentare i volumi e la velocità di scambio.

Una delle cose che oggi viene fatta in modo non completo, migliorabile è quella di usare le crypto come moneta di pagamento: questo trasforma un valore digitale in valore fisico se l’utente acquista un prodotto con le crypto.

Questa cosa viene favorita in Syncrony Exchange usando un Pay Component: è uno strumento scritto in Java Script, quindi molto facile da inserire all’interno di siti web ed app mobile, senza la necessità che l’utente si installi nuovi strumenti.

Tutto questo ha l’obiettivo di favorire in maniera molto spinta la spendibilità delle criptomonete all’interno di: E-commerce Portali che vendono servizi e prodotti

Tutto ciò fatto come se fossero monete reali.

L’esercente riuscirà quindi, con Synkrony Exchange ed il Pay Component, ad entrare nel bacino di utenti che spendono criptomonete per acquistare prodotti o servizi. Gli utenti di base, invece, avranno due strumenti che faciliteranno la spendibilità delle proprie criptomonete, indipendentemente che esse siano state acquistate o che siano state guadagnate attraverso il mining.

Gli utenti che investono nella blockchain acquistando token che non hanno dei sottostanti effettuano delle scommesse al pari del “Gratta e Vinci”: a qualcuno va bene, ma alla maggior parte degli utenti va male.

Cosa diversa è se l’utente investe su prodotti pensati per ottenere valore a lungo termine, mentre nel frattempo usa cripto come bene di scambio per acquistare prodotti o servizi che magari hanno dei privilegi in quanto acquistati attraverso le cripto.

Tali privilegi si creano poiché questo sistema disintermediato riduce drasticamente i costi di gestione: il merchants che decide di usare il Pay Component per fare acquisti si trova molti meno costi nella gestione di tali acquisti e quindi riesce ad attuare sconti o sistemi di Priority per tutti coloro che utilizzano cripto per acquistare i suoi prodotti. Questo è un esempio di vantaggio tangibile.

6.2 Vantaggi - Value Propositions.


Synkrony Pay è un’infrastruttura di pagamento DeFi che consente ad ogni negozio fisico o e-commerce di incassare crypto in modo decentralizzato e valuta FIAT nel circuito SEPA, in totale sicurezza e nel rispetto delle normative vigenti.

  • Nessun intermediario fisico nella gestione degli incassi in crypto tra venditore e compratore, ma intermediazione tramite blockchain (Escrow Service).
  • Il Wallet di incasso del merchant può essere connesso a un conto bancario, collegato ad una carta di debito su circuito Mastercard, per la sicura conversione dei fondi in Euro (unica soluzione attualmente presente sul mercato di integrazione di un sistema crypto con un sistema bancario).
  • Garanzia della sicurezza sia del compratore che del venditore con un servizio di refound gestito esclusivamente dalla tecnologia blockchain (Escrow Service).
  • Facile da integrare nel tuo shop online, in App o tramite Pos.
  • Dashboard per la gestione del portafoglio e delle transazioni.
  • Integrazione con i principali wallet sul mercato per ricevere criptovalute.

6.3 Fees - Commissioni


Nessun costo di installazione, nessun abbonamento, nessun minimo di transato e gestione del wallet gratuita su Synkrony Exchange per la conversione di Crypto in Euro.

Commissioni di incasso in crypto: 1%. Commissioni di incasso in Carta: a partire dall’ 1,8% in base alla categoria merceologica

6.4 Flusso di Iscrizione e configurazione


  1. Richiesta iscrizione del merchant tramite appoisto form on line https://forms.affidaty.io/pay-component-request
  2. Creazione del wallet “business” su Synkrony Exchange tramite creazione di identità digitale del merchant
  3. Compilazione della tabella SPR per il calcolo della minima commissione applicabile in base al rischio della categoria merceologica venduta dal merchant
  4. Abilitazione all’installazione del plugin di pagamento
  5. Installazione del plugin di pagamento nel proprio e-commerce (a cura del System Integrator o del reparto IT del merchant)
  6. Configurazione del sistema di pagamento: scelta delle modalità di incasso (Crypto o Carta di debito o credito)

Esperienza utente e workflow di funzionamento

6.6 Pagamento classico tramite Carta


Selezionando “Pay with Card” si aprirà il campo per inserire le informazioni della carta.



PayComponent_1



Cliccando il tasto verde sulla destra verrà confermato il pagamento e l’utente sarà reindirizzato nella pagina di conferma con il riepilogo delle informazioni inserite per la conclusione dell’operazione.



PayComponent_1



6.7 Pagamento con Crypto


Selezionando “Pay with Bitcoin” e cliccando sul pulsante verde per procedere al pagamento, l’utente viene indirizzato nella sezione riservata al pagamento con le Crypto.



PayComponent_1



In questa sezione l’utente avrà 2 opzioni:

Accedere al proprio wallet Synkrony per confermare la presenza dei fondi e procedere al pagamento. Acquistare l’esatta quantità di Bitcoin con carta di credito e procedere al pagamento

L’opzione (2) potrebbe essere utile qualora il merchant decidesse di vendere il prodotto presente nel carrello soltanto in cambio di Bitcoin e l’utente compratore ne fosse sprovvisto. In questo caso il sistema creerà automaticamente per l’utente acquirente un wallet “usa e getta di scopo”, adibito soltanto alla ricezione dei Bitcoin, acquistati con carta, che istantaneamente verranno trasferiti nel wallet del merchant. Il wallet “di scopo” creato verrà disabilitato al termine dell’operazione senza alcuna iscrizione o disicrizione da completare da parte dell’utente.

Proseguendo con l’opzione (2) il flusso di operazione per l’utente sarà analogo ad un semplice pagamento con carta come descritto nel paragrafo precedente.

Seguendo per l’opzione (1) ovvero accedendo al Wallet Synkrony potranno verificarsi altre 3 opzioni:

Utente già in possesso di un wallet Synkrony provvisto della quantità di Bitcoin per completare l’operazione Utente già in possesso di un wallet Synkrony ma sprovvisto della quantità di Bitcoin per completare l’operazione Utente non registrato che possiede Bitcoin ma non nel wallet Synkrony



PayComponent_1



Opzione (1), l’utente ha un wallet Synkrony con un saldo superiore o uguale alla quantità richiesta nel carrello a destra, completa il pagamento cliccando sul pulsante verde e conclude l’operazione.



PayComponent_1



Opzione (2) l’utente ha un Wallet Synkrony con un saldo di Bitcoin inferiore alla quantità richiesta nel carrello. In questo caso dovrà ricaricare il proprio wallet Synkrony di altri Bitcoin e potrà farlo con 2 semplici modalità

La prima è acquistando nuovi Bitcoin con carta proseguendo come un normale acquisto con carta.



PayComponent_1



La seconda modalità è usufruendo di Bitcoin provenienti da un altro wallet (es. Coinbase, Binance, ecc) o direttamente dalla catena pubblica di Bitcoin. In questo caso basterà inquadrare il QRCODE generato dal sistema e seguire le operazioni direttamente nell’app del provider gestore dei Bitcoin al di fuori di Synkrony.



PayComponent_1



Una volta trasferiti i fondi si potrà concludere l’operazione.

Qualora non si fosse in possesso di un wallet Synkrony, opzione (3) basterà completare la procedura di iscrizione e ricaricare il wallet appena creato seguendo le 2 modalità del paragrafo precedente, con carta o tramite Bitcoin provenienti da altri gestori.

Tutte le procedure sopra descritte saranno applicabili a tutte le principali crypto del mercato, in questo caso è stato analizzato il caso più diffuso: il pagamento tramite Bitcoin.

6.8 Scarico del Wallet e accredito sul conto


Una volta incassate le crypto, il merchant potrà convertirle in Euro digitali (#Eurs) per essere scaricati oppure potrà inviarli in catena pubblica o ad un altro wallet (es. Coinbase, Binance).

In questo paragrafo analizziamo come un merchant potrà convertire in Euro le crypto o gli euro digitali incassati tramite il Synkrony Pay Component.

Le operazioni di conversione in Euro e ritiro dei fondi sono gestite da Synkrony Exchange direttamente nella dashboard di gestione del merchant. Qui i Bitcoin incassati potranno essere convertiti in Euro digitali e successivamente potranno essere ritirati.

Tutte le operazioni vengono gestite tramite l’Action component di Exchange, sempre presente sulla destra della piattaforma, tramite i comandi: COMPRA - CAMBIA - RITIRA

Un merchant che quindi vorrà trasferire Bitcoin in catena pubblica o direttamente in un altro wallet extra Synkrony potrà usare il comando RITIRA e seguire la procedura di withdraw esterna al circuito

Un merchant che vorrà cambiare i Bitcoin in Euro digitali (#Eurs) dovrà prima eseguire il comando CAMBIA e selezionare la valuta in cui si desidera cambiare i Bitcoin, in questo caso #Eurs.

Una volta in possesso di #Eurs (Euro Digitali) il merchant potrà richiedere un bonifico dei fondi nel proprio conto corrente.

Data la non familiarità delle principali istituzioni finanziarie con il mondo delle criptovalute, Synkrony offre la possibilità ai merchant di usufruire di un servizio Banking integrato che garantisce l’istantaneo e sicuro trasferimento degli #Eurs in un conto corrente all’interno del circuito Synkrony dotato di IBAN e carta di debito per la completa gestione dei fondi con le normali operazioni di conto corrente.

7.1 - Network di notarizzazione




IndependentChain_1



IndependentChain è il network di notarizzazione: ogni HDSB può autenticarsi sulla catena principale tramite l'ancoraggio. Inoltre è prevista una rete di test dedicata agli sviluppatori per le prove sugli smart contract.

Independent Chain è una PPDLT (Public Permissioned Distributed Ledger Technology) ed è un network formato da quattro tipi di reti per processare le transazioni della blockchain T.R.I.N.C.I.:

Rete Alpha - I nodi Alpha, installati direttamente all’interno delle Server Farm, garantiscono i massimi livelli di sicurezza sia informatica che fisica, godendo dei massimi standard strutturali, energetici e di manutenzione. I nodi alfa sono deputati alla notarizzazione dei blocchi delle HDSB (High Density Scoped Blockchain). Rete Beta - Beta è la rete dell HDSB specifiche che decidono di fare anchoring su Alfa, è costituita da fitlet di proprietà degli utenti finali che svolgono un ruolo di nodo di servizio e da nodi di validazione gestiti dalla rete Alfa (soltanto i nodi di validazione hanno diritto alla ripartizione dei Bitbel secondo gli schemi sotto illustrati). Rete Gamma - E’ un tributo a Bitcoin, il cui consenso è basato sulla Proof Of Work con le stesse dinamiche e gli algoritmi di Bitcoin ma realizzato su Core T.R.I.N.C.I.2. Rete Omega - Da una comunità di sviluppatori T.R.I.N.C.I. 2.0, la rete Testnet offre al mercato potenza di calcolo autonoma.

T.R.I.N.C.I. 2.0 ha a disposizione una catena principale su cui ogni HDSB può ancorare. Gli HDSB utilizzano la catena principale per autenticare gli hash del blocco in maniera indipendente dal loro funzionamento, garantendo maggiore flessibilità e scalabilità al sistema. Ci sono nodi di validazione all'interno di questa blockchain che, in base all'algoritmo di consenso assegnato, certificano i blocchi e autorizzano i miner a svolgere il loro lavoro di certificazione della catena.

Il validatore e i nodi di servizio nella rete sono identici ma distinti, il che significa che ogni nodo si identifica con la propria chiave pubblica. I nodi Validator devono essere dotati di un Trusted Platform Module, che genera la chiave pubblica responsabile della firma delle transazioni.



IndependentChain_1



7.2 - Alpha Network




IndependentChain_3



La rete superiore di validazione Alpha è costituita da nodi validatori subordinati all'ancoraggio di blocchi che appartengono alla rete Beta.

I nodi Alpha, installati direttamente all’interno delle Server Farm, garantiscono i massimi livelli di sicurezza sia informatica che fisica, godendo dei massimi standard strutturali, energetici e di manutenzione. I nodi alfa sono deputati alla notarizzazione dei blocchi delle HDSB (High Density Scoped Blockchain).

Il network Alfa garantisce il funzionamento dei nodi e dà diritto ai miners di essere remunerati. Le sue principali funzioni sono: Signature Server: permette ad un nodo qualsiasi di attestarsi in modo efficiente sulla catena, in quanto identifica e coordina in modo efficiente tutti gli indirizzi dei nodi funzionanti appartenenti a quella rete. Il protocollo Kademlia usato dai nodi sarebbe in grado da solo di identificare tutti i nodi senza questo servizio, ma impiegherebbe ore per il network discovery. E’ una rete di computer ben visibili, su cui gli altri nodi possono fare anchoring, tramite protocollo Kademlia. Anchoring: il nodo validatore va ad inserire dei blocchi notarizzati all’interno della catena di notarizzazione. Mining, contabilità e remunerazione Bitbēl: IC-Alfa esiste un nodo su IC-Beta Affidaty, perché Affidaty ha costruito un modello che potrà essere replicato su altri.

I Bitbēl che vengono minati su IC-Alfa, vengono trasferiti in IC-Beta all’interno dell’Exchange e questo ne garantisce il cambio a seguito di tutte le transazioni effettuate all'interno della IC-Beta. In questo modo i miners di IC-Alfa vengono remunerati in funzione del business e delle transazioni effettuate all’interno della HDSB-IC Beta, in base alla loro percentuale di nodi posseduti (identificati dall’ IDC - IndependentChainCoin). Sono loro ad immettere i Bitbēl all’interno della Beta per garantire il funzionamento.

IC-Alpha stabilizza e collega le IC-Beta, costituendo un ponte, in grado di far scambiare i dati tra tutte le IC-Beta dislocate nel mondo, e con scopi di business diversi, come ad esempio lo scambio di NFT di film d’autore o la quotazione delle varie monete, che altrimenti sarebbero relegate solo alla singola rete. Rende possibile il principio di Allotment, paragonabile ad una sorta di Explorer di tutte le reti nel mondo che impiegano T2.

7.3 - Beta Network - Mainet




IndependentChain_4



Beta è la rete delle HDSB specifiche che decidono di fare anchoring su Alfa, è costituita da fitlet di proprietà degli utenti finali che svolgono un ruolo di nodo di servizio e da nodi di validazione gestiti dalla rete Alfa (soltanto i nodi di validazione hanno diritto alla ripartizione dei Bitbel secondo gli schemi sotto illustrati).

Le reti beta sono costituite da nodi validatori e nodi di servizio. Questi hardware sono tecnicamente e praticamente identici. È l'algoritmo di consenso condiviso per stabilire in modo univoco, deterministico e imprevedibile i validatori dei blocchi successivi. Ogni HDSB si distingue per una specifica configurazione di rete, ovvero per il file che ne definisce la dinamica:

  • Dimensione del blocco
  • Frequenza dei blocchi di chiusura
  • Algoritmo di consenso
  • Contratti intelligenti
  • Nonce
  • Versione principale

Con T.R.I.N.C.I. 2.0 si possono creare blockchain specifiche per ogni contesto, chiamate HDSB - High Density Scoped Blockchain, ciascuna può essere implementata con una propria rete dedicata e un proprio algoritmo di consenso.

Il primo network Beta, formato da nodi certificati su server farm, è stato creato sotto l’iniziativa di Affidaty S.p.A. ed altri partner tecnici hardware per l’esecuzione degli smart contracts di Exchange, Escrow System, custom coin, Voting system, Time Stamp ecc.

La Network Beta di Affidaty si chiama MAINET. Ogni utente può decidere di implementare sulla beta esistente i propri smartcontracts ed usufruire di tutti i servizi bancari connessi oppure può decidere, per scopi personali, di crearsi una propria rete Beta con una propria HDSB dedicata, con la stessa tecnologia e lo stesso core ma con un diverso modello di business.

Ogni rete beta di iniziativa privata supporta un Hardware specifico, progettato da Affidaty S.p.A., per garantirne la massima efficienza energetica e di prestazioni, il quale sarà a carico del creatore del progetto stesso. Nell’eventualità che una rete beta privata voglia operare come sistema pubblico per garantire che i dati non siano alterati, Independent Chain dà la possibilità di notarizzare tutti i blocchi della HDSB privata nel Network Alpha.

Così facendo un network beta può notarizzare i suoi blocchi sul network alpha per garantire sia il business con tutta la privacy dei dati inseriti sia che nessun dato venga alterato dai possessori dei nodi. Un esempio di questo modello di rete Beta con notarizzazione dei blocchi su rete Alpha è proprio Affidaty S.p.A., la quale garantisce a tutti i suoi utenti la massima performance ed efficienza dei sistemi privati ma anche la sicurezza dei sistemi pubblici.

E’ stato previsto un protocollo di sicurezza Open Source Injection che garantisce l’integrità del codice di T2 impiegata nelle singole HDSB, in grado di impedire la comunicazione con la rete Alpha se il codice è stato modificato o manomesso.

Il gas necessario all’utilizzo degli smart contract nelle singole HDSB sono i Bitbel, ed ogni soggetto che fa parte della HDSB li può acquistare su WowExchange in maniera autonoma, così da consumare bitbel per effettuare ogni singola transazione.

La strutturazione di una HDSB su rete privata di proprietà avrà maggiori costi iniziali di struttura ma non avrà poi i costi di gestione di una blockchain pubblica, dove secondo un determinato modello di business, per ogni operazione corrispondono delle fee.

7.4 - Gamma Public Network


Gamma è il network con lo stesso algoritmo di consenso PoW e lo stesso modello di generazione di monete di Bitcoin, ma implementato sul core di T.R.I.N.C.I. 2.0. Come nella blockchain di Satoshi Nakamoto saranno minabili 21.000.000 monete, i Syn, i quali saranno estratti con lo stesso algoritmo di alving, per creare un vero e proprio tributo a Bitcoin.

Gamma quindi è il network pubblico dove chiunque abbia una schede video performante può diventare minatore, poiché l’algoritmo di mining è basato su una brute force sull’hash tale e quale a quello di bitcoin.

In riferimento a BitCoin, alle criptovalute basate su PoW e alle Mining Pool, uno schema popolare è il Pay-Per-Last-N-Shares (PPLNS), che retribuisce i miner solo quando la pool mina un blocco con successo.

Quando la pool trova un blocco, controlla l'ultima quantità N di share inviate (N varia in base alla pool). Per calcolare il pagamento del miner, divide il numero di share che ha inviato per N, quindi moltiplica il risultato per la block reward (sottraendo la commissione dell'operatore). Facendo un esempio: se l'attuale block reward è di 12,5 BTC (supponendo zero commissioni di transazione) e la commissione dell'operatore è del 20%, la ricompensa disponibile ai miner è 10 BTC. Se N è 1.000.000 e tu un miner ha inviato 50.000 share, riceverà il 5% della ricompensa disponibile (o 0,5 BTC).

7.5 - Omega Testnet


Tutti gli sviluppatori certificati T.R.I.N.C.I. 2.0 sono dotati di una rete di test che comprende tutti i nodi di proprietà di ciascuno sviluppatore, denominata “Omega testnet”. La rete di test è progettata specificamente per lo sviluppatore, per testare i contratti intelligenti e vedere come rispondono prima di essere eseguiti. Gli asset per l'esecuzione delle transazioni sono svincolati su richiesta e non hanno alcun valore al di fuori del Testnet.

La blockchain di test viene costantemente ripristinata e pulita in modo che sia sempre chiara e non si possa riscontrare alcun degrado delle prestazioni.

Il modello di business è lo stesso della rete IC-Alpha, e verrà coinvolta la Community per stabilire i costi dei bitbel che sono notevolmente più bassi della IC-Apha.

7.6 - Independent Chain Coin (IDC)


7.6.1 Descrizione


Perché è stato introdotto e perché in T.R.I.N.C.I. viene incentivato l’uso di Independent Chain con il Independent Chain Coin?

In tutte le blockchain note, normalmente, per registrare una transazione si deve pagare qualcosa. In Bitcoin è una fee sui bitcoin stessi, in Ethereum esiste una moneta dedicata (il Gas).

Queste monete sono atte a finanziare i miners che tengono notte e giorno accesi i propri computer, cioè i propri nodi, per tenere in vita tutto il sistema e permettere agli utenti di poter registrare transazioni. Questo è un ruolo importante ed è quindi importante che queste monete vengano direzionate verso chi effettua un lavoro così importante. Alcune blockchain note stanno pensando di azzerare tali fee, ma se questo è un vantaggio a breve termine, sarà un grosso svantaggio a lungo termine perché non permetterà ai minatori di svolgere il loro ruolo molto importante.




7.6.2 Chi è il beneficiario delle transazioni.


Nel caso delle blockchain note si tende a fondere due aspetti: l’aspetto della validazione, quindi l’aspetto tecnologico che consente la scelta del nodo di validazione, e l’aspetto del beneficiario delle fees. Quindi: colui che diventa un nodo di validazione per quello specifico blocco prende anche il guadagno delle fees di quello specifico blocco.

In T.R.I.N.C.I. è stata fatta una scelta diversa, motivata da tanti aspetti. Sono state separate in due layers quelle che sono la validazione tecnologica e la distribuzione delle monete, creando appunto l’algoritmo di distribuzione POP : Proof of Play.

Questo consente di:

  • allineare i nodi usando uno dei migliori algoritmi di consenso noti, RAFT, rivisitato tecnologicamente per adattarlo al meglio al contesto creato: algoritmo di consenso molto efficiente, veloce, stabile, Anti-Fork.
  • Distribuire i profitti tramite l’algoritmo di distribuzione dei profitti POP, basato sullo stake.



7.6.3 Proof of Stake, il problema.


Oggi, nel mondo blockchain, è molto seguita la via del Proof of Stake da svariati soggetti, ma le tecnologie blockchain di nuova generazione per questioni di prestazioni ed efficienza si portano dietro un problema abbastanza noto: l’utilizzo dei numeri a virgola mobile.

I calcoli che vengono fatti con l’uso della virgola possono essere diversi da computer a computer.




7.6.4 Esempio.


Se svolgo un'operazione di frazione su un numero primo come 1/17, otterrò un certo numero con la virgola. la stessa frazione eseguita da un computer Intel, Mac o da un cellulare può dare come rappresentazione visiva finale un risultato differente, risultando modificati gli ultimi numeri dopo la virgola secondo arrotondamenti effimeri.

Sono arrotondamenti effimeri, si, ma quanto basta per effettuare un disallineamento di hash. Quindi, se io vado a creare un numero a virgola mobile deterministico ho delle complessità di carattere tecnologico che derivano dall’uso intimo che fa la blockchain del processore. Per motivi prestazionali, oggi la blockchain è un prodotto compilato e parla direttamente con il processore; addirittura a seconda del processore che opera esistono delle operazioni di compilazione diverse per motivi di prestazioni. Questo però fa sì che se si calcola 1/17 su due nodi che hanno due hardware diversi ho un’alta probabilità che il risultato sia leggermente diverso, quanto basta per creare degli hash completamente diversi.




7.6.5 Algoritmo di distribuzione: la soluzione POP & DRAND


In alcune tecnologie vengono fatti alcuni arrotondamenti che comportano comunque delle complessità; in T.R.I.N.C.I. abbiamo deciso di conservare quello che è l’anima intima di una blockchain utilizzando solo numeri interi, non a virgola mobile.

Questa scelta ci permette comunque di fare simulazioni a virgola mobile, ma la parte pura rimane a numeri interi. Questo rende complessa la suddivisione delle commissioni in maniera efficace.

Se lo smart contract deve dividere 23,00 € di fees per 17 persone, deve necessariamente entrare in merito ai numeri a virgola mobile necessari per gli arrotondamenti, poiché 23 diviso 17 non restituisce un numero intero. Questo porta a delle complessità nella distribuzione dei profitti.

Questa situazione viene risolta con l’algoritmo di distribuzione POP che fondamentalmente utilizza dei principi diversi, vediamoli:

  1. viene estratto a sorte un beneficiario sulla base degli stakers, quindi sulla base delle persone che hanno deciso di minare quel tipo di moneta facendo un investimento meccanico cioè acquistando moneta e mettendola in stake per diventare miner;
  2. chiaramente in un algoritmo di stake ci saranno diversi stakers con diverse monete. Ci sarà qualcuno che avrà messo in stake 100, qualcuno 1000 e così via;
  3. tirare a caso tra questi soggetti in realtà non sarebbe democratico poiché la probabilità di uno dei soggetti di diventare minatore (riscuotendo il compenso) dovrebbe esser influenzata dalla quantità di monete che ha/hanno messe in stake;
  4. su questo la stocastica ci offre varie soluzioni: quella adottata in T.R.I.N.C.I. è una soluzione di “Random Deterministico Pesato”:
    • è molto complicato in un sistema deterministico creare un numero randomico;
    • in T.R.I.N.C.I. abbiamo risolto questo problema creando un algoritmo di D Random che significa “Random Deterministico”;
    • può sembrare un ossimoro (D Random), ma nella praticità siamo in grado di far lanciare una moneta, un dado, quindi creare un numero randomico in un nodo in un determinato momento e tutti i nodi in quel determinato momento ottengono lo stesso numero randomico anche se sono disallineati temporaneamente o dislocati in posti diversi del globo;
    • con questo algoritmo, che avrà in questo documento una spiegazione dedicata, in T.R.I.N.C.I. siamo in grado di generare un numero randomico imprevedibile, ma deterministico, su tutti i nodi che in un determinato momento vanno a richiedere un numero randomico;
    • questo ci aiuta ad estrarre a caso un destinatario delle fees, senza andare a dividere le fees con tutti gli stakers:
    • per ogni transazione, quindi, si estrae a caso con il DRAND uno staker e lui si prende tutte le fees;
    • il problema è stato risolto, ma la soluzione potrebbe sembrare non democratica: in realtà è stato studiato che il fatto di estrarre “a caso” gli utenti alla fine porta ad una distribuzione effettivamente stocastica. Se io lanciassi una moneta per 100.000 volte la probabilità che mi esca testa o croce è del 50%. Questa cosa non sarà certamente vera nei primi 2 o 3 lanci, ma mano a mano che il numero dei lanci diventa enorme la curva converge verso la distribuzione 50 e 50;
    • ma in T.R.I.N.C.I. non cerchiamo un algoritmo che distribuisca le fees delle transazioni 50 e 50 tra 2 miners, bensì di un algoritmo che nella distribuzione tenga conto anche del peso di chi ha messo in stake più monete di un altro;
    • ecco che l’algoritmo POP propone un approccio stocastico deterministico creando una sorta di “dado truccato” nel senso buono del termine: la probabilità che esca uno staker è proporzionale rispetto a quante monete ha in stake;
    • esempio: se un soggetto avesse il 50% dello stake e altri 2 soggetti 25% e 25%, la probabilità che esca il primo è del 50%, mentre la probabilità che esca il secondo o il terzo è del 25%. Sui primi lanci la distribuzione così fatta potrebbe risultare letta come non così discreta, ma a lungo termine lanci e distribuzione diverranno distribuiti.

Il processo fin qui spiegato rende molto efficiente la distribuzione dei profitti; non c’è un algoritmo scalare interno, come per esempio il Round Robin. Il problema di sistemi meccanici come il Round Robin è che possono funzionare bene solo in un sistema centralizzato: questo vorrebbe dire che in un sistema distribuito dovrebbe esistere un soggetto centralizzato che tiene in ordine il round robin, quindi si ricadrebbe di nuovo nel problema di essere di fatto in un sistema distribuito, ma con un'autorità centrale.

Ad oggi, quindi, il POP rappresenta secondo T.R.I.N.C.I. quello che è la punta di diamante di tutte quelle che sono le tecnologie e la scienza intorno alla materia della stocastica, messe a frutto in un sistema distribuito, tenendo conto delle enormi complessità che un sistema distribuito si porta necessariamente dietro per motivi tecnologici.




7.6.6 Diventare un miner


Per diventare un miner è necessario acquistare i “gettoni” del miner, cioè gli Independent Chain Coin. Questo dà diritto a ricevere una percentuale di profitto tramite l’algoritmo appena spiegato su tutto il “Gas Fee” consumato all’interno della blockchain di T.R.I.N.C.I.




7.6.7 Come funziona: il BitBel.


Oggi il miner è proprietario di una fetta dei guadagni. Dove sono i guadagni? Gli utenti interessati a far lavorare le transazioni in blockchain devono acquistare questo BitBel per poter permettere di validare una o più transazioni.

Tramite l’algoritmo POP, questi BitBel vengono distribuiti a pioggia da parte di tutti i possessori degli Independent Chain Coin secondo la distribuzione stocastica di cui abbiamo parlato. Il miner può prendere questi BitBel e rivenderli sul mercato per guadagnare dai BitBel ottenuti. Il sistema funziona indipendente dal fatto che un miner abbia un hardware suo dedicato per fare mining.




7.6.8 Il problema dei costi delle fees.


Il modello di prezzo del BitBel è diverso da quello del classico gas fees delle altre tecnologie blockchain. Nella maggior parte delle tecnologie blockchain come Ethereum o Bitcoin, il prezzo di queste monete cresce all’aumentare dell’uso di questa tecnologia.

Questo è certamente un buon modello, funziona, ma che tende a diventare proibitivo per tutti coloro che usano la blockchain per fare business. Se oggi devo fare un’unica transazione, pagarla 1€ o 5€ non è molto oneroso, ma ripetiamo, una singola transazione. Se invece devo sviluppare un modello di business che può generare 100.000 transazioni, pagare 1€ o 5€ per singola transazione cambia molto il costo totale.

Quindi, in un contesto in cui il prezzo non è prevedibile, moltissime aziende si trovano a dover affrontare da subito un ostacolo molto importante in relazione all’uso della tecnologia blockchain nel proprio ambito di business.




7.6.9 La soluzione in T.R.I.N.C.I.


In T.R.I.N.C.I. abbiamo creato, per questo, un modello opposto: se l’azienda vuole fare semplicemente delle prove, dei test e quindi ha bisogno di poche transazioni, quelle poche transazioni costano tanto. In T.R.I.N.C.I. “tanto” corrisponde a 25 centesimi di Euro a transazione.

Ma nel momento in cui l’azienda avesse necessità di fare molte transazioni, può acquistare preventivamente grandi quantità di BitBel ed il modello di vendita di essi offre un prezzo sempre minore in relazione a quanti più BitBel vengono acquistati.

Questo modello sta in piedi poiché l’algoritmo di consenso di T.R.I.N.C.I. non è energivoro come in BitCoin o in Ethereum. Il costo di un nodo è pressoché indipendente dal fatto che sia acceso o spento, visto che il nodo consuma 15 watt, un cellulare in carica consuma molto di più.

Per un miner è interessante sapere se qualcuno ha investito 1 milione di Euro in gas all’anno per i prossimi 3 anni ed il miner avrà tutto l’interesse a tener acceso e funzionante il proprio nodo, per incassare quei 3 milioni di Euro. In questo senso il miner si accontenterà di aver venduto BitBel ad un prezzo più basso poiché in questo modo si è garantito i guadagni futuri derivanti dall’azienda che ha acquistato i BitBel che immetterà per far lavorare le transazioni ad essa necessarie.

Diversamente, se arriva un utente che acquista solo 100 monete, il miner non avrà la stessa garanzia di continuità rispetto all’utente che ne ha acquistate 1 milione all’anno; quindi, il miner venderà quei 100 BitBel ad un prezzo più alto rispetto al prezzo per i 3 milioni di Bitbel dell’altro utente.

Per chiarezza, il prezzo dei BitBel oscilla tra 25 centesimi di € a transazione ai 5 millesimi di € a transazione, rendendo di fatto possibile la notarizzazione ad aziende che hanno bisogno di notarizzare milioni di transazioni.




7.6.10 L’hardware di mining.


Per essere minatore nelle HDSB di classe Beta, avendo un riferimento costante alla classe Alfa, di per sé non è necessario comprare un hardware di mining, poiché è opzionale l’anchoring ad Alfa Independent Chain.

Qualora, invece, si volesse fare anchoring su Independent Chain diventa necessario avere un hardware certificato, questo perché quest’ultimo ha delle caratteristiche importanti; una su tutte è l’avere il modulo TPM a bordo.

Questa è una caratteristica non necessariamente presente ad oggi su tutti gli hardware in commercio: se per esempio un utente accende un nodo su docker, essendo un nodo virtuale non avrà un modulo TPM a bordo nonostante esistano driver (o trucchi vari) per tentare di farlo funzionare.

Affidaty stessa vende questi tipi di hardware: sono dei piccoli hardware che consumano 15 watt di potenza, già pronti all’uso. Non esiste una obbligatorietà al loro uso, ma esistono una serie di caratteristiche necessarie di tipologia e specifica di hardware. Se queste specifiche non vengono rispettate, nel momento in cui le perde, il nodo viene interrotto dal sistema e viene blacklistato come nodo di validazione all’interno di Independent Chain

8.1 Cos’è ABS




ABS_1



Affidaty Blockchain Services (ABS) è un ambiente nel quale convergono tutti i pannelli di controllo dei vari Smart Contract. E’ una piattaforma dedicata ed appositamente costruita per essere lo Store T.R.I.N.C.I. dei servizi e smart contract di Affidaty.

Gli Smart Contract non hanno effettivamente bisogno di pannelli di controllo per funzionare, poiché essi contengono già dentro di sé tutte le regole per funzionare e sono già implementati in background sulla chain. Quando però si interagisce con gli utenti, risulta chiaro come sia fondamentale la presenza di uno o più pannelli di controllo che permettano agli utenti di interagire con (i loro asset).

ABS facilita l’utente in questo, poiché mette a disposizione gratuitamente un SDK (Software Development Kit) che fa risparmiare un buon 80% del lavoro poiché fornisce già completa quella parte complessa di autenticazione, login, area riservata, distribuzione delle pagine sulla base dei ruoli degli utenti, accessi multipli alla stessa risorsa..

Questo SDK offre tanto fin dall’inizio ed in più fornisce la possibilità di poter ridistribuire il pannello di controllo. Ad esempio possono essere distribuite delle subscription a pagamento, ovvero colui che si crea un proprio token potrebbe avere tanti utenti che hanno interesse ad accedere ad una dashboard per monitorare quello che succede e di nuovo questa dashboard potrà essa stessa essere distribuita (venduta) come nuovo modello di subscription.

Immaginiamo qualcuno che costruisca una galleria d’arte in NFT: il fatto stesso che questa galleria d’arte sia accessibile nei suoi dati analitici o nelle sezioni riservate, con la tecnologia ABS si ha la possibilità di rivendere questa sottoscrizione. La blockchain T.R.I.N.C.I. funziona indipendentemente dalla subscription, ma tutto l’investimento per la creazione di interfacce, analitiche, regole e quant’altro possono essere un valore aggiunto.

ABS è per certi aspetti l’anello di congiunzione tra cloud e blockchain: questo perché ABS è un prodotto in cloud. È un portale vero e proprio che, come tutti i prodotti in cloud, ha i suoi principi di funzionamento standard: username e password, acquisti per sottoscrizione eccetera. Risulta essere uno specchio di monitoraggio di ciò che avviene in modalità disintermediata, ecco perché è l’anello di congiunzione tra i due.

Dentro ABS esiste il pannello di controllo di Eurs; quindi dentro il pannello di controllo di Eurs si può vedere a tutti gli effetti ciò che succede in blockchain, si possono creare cloni di Eurs, si possono monitorare alcuni wallet, tutta una serie di attività che avvengono in cloud. Tutto questo non sarebbe possibile farlo se sotto a questa tecnologia non esistesse un produttore di dati in blockchain che è disintermediato.

Tutto questo viene fatto usando una tecnologia particolare: i pannelli di controllo possono essere remoti. Quindi lo sviluppatore che crea il proprio pannello di controllo lo crea nel proprio server, senza portare nulla in ABS. Successivamente un SDK permette, tramite iFrame arricchiti con dati crittografici, di portare all’attenzione dell’utente un contenuto di un pannello di controllo che in realtà viene prodotto altrove, mantenendo l’esperienza utente interna al sistema.

8.2 Perché ABS


E’ l’anello che unisce in modo fluido: Core T2. Smart Contract. Servizi. Applicativo del cliente. Monitoraggio e controllo (Singoli explorer dei servizi).

ABS fornisce all’utente tutti i dati per costruire, in modo indipendente, i grafici, senza entrare in ambito back end. L’utilizzatore si collegherà, infatti, ad ABS per costruire il pannello di controllo del proprio smart contract o servizio.

Entriamo più nel dettaglio di cosa può fare ABS:

Censire un servizio, dichiarare dove si trova il pannello di controllo di un determinato servizio. Gestione del proprio profilo. Gestione dei prodotti/servizi acquistati, con azioni di admin (Dettagli del servizio, Recesso, Help) Funzioni di ricerca in tutto ABS e nei miei Servizi. Categorizzazione dei servizi/smart contract (così da premettere una ricerca o elencazione più chiara per l’utente/sviluppatore). Uso SignTx. Continua adattabilità della piattaforma, per modificare e aggiornare l'interfaccia. Omogeneità per aumentare UX. Pannelli di gestione dedicati agli Smart contract/Servizi: Il pannello è raggiungibile al click sullo Smart contract o servizio presente nella sidebar laterale (o elenco servizi attivi) dopo l’acquisto o attivazione. Si apre in un iframe (“finestra” che carica un “sito web” esterno in una pagina html) al centro pagina, quindi il pannello sarà ospitato su un dominio dedicato (di Affidaty o cliente), richiamato visivamente da ABS nell’iframe. Il design dovrà essere altamente integrato con ABS quindi le scelte sono 2: usare la stessa tecnologia di ABS (ionic, vue, tailwindcss) o una dedicata (Tailwindcss, Vuejs) “preconfezionata” con classi e stili di base progettati per essere visivamente in linea con il contenitore ABS. Creazione dei pannelli. La tecnologia scelta permette di essere sempre in linea con ABS al fine di non doverli costantemente modificare con il rilascio di nuovo codice, bensì solo aggiornarli. Nell’ottica di far creare i pannelli anche a clienti/integratori/sviluppatori è ancora più importante che la tecnologia usata sia già “preconfezionata” per ottenere un risultato visivo e di UX. Viene fornito, quindi, un pacchetto scaricabile con la preinstallazione di base demo (es. Tailwindcss + Vuejs) con cui il cliente potrà creare il pannello di gestione. In futuro verrà preparata una configurazione guidata del pannello preinstallato permettendo di scegliere gli elementi da inserire da “librerie proprietarie”.

Per permettere un aggiornamento più veloce del codice, in futuro è previsto l’uso di CDN proprietarie Affidaty su cui saranno ospitati script e css principali.

8.3 Cosa può fare l’utente con ABS




ABS_2



ABS (Affidaty Blockchain Services) è un servizio messo a disposizione sia per utenti di base che per utenti sviluppatori che lo vorranno usare in modo tecnico.

  • Qualsiasi utente può registrarsi, creando una propria utenza:
    • per poter sottoscrivere ed utilizzare uno smart contract o un servizio.
  • Qualsiasi utente può avere più informazioni possibili prima di sottoscrivere uno smart contract o un servizio:
    • il servizio è in abbonamento? È lifetime?
  • Qualsiasi utente può recedere da uno smart contract/servizio se si tratta di contratto in abbonamento:
    • qualora sia stato attivato per errore;
    • qualora l’utente sia insoddisfatto;
    • qualora l’utente voglia interrompere semplicemente il servizio.
  • Lo sviluppatore può creare un pannello di controllo:
    • per esempio per poter gestire il proprio smart contract.
  • Lo sviluppatore può avere una panoramica esauriente (tabella comparativa classica) per avere delle istruzioni chiare e comprensibili a step:
    • per esempio per creare il proprio pannello di gestione smart contract/servizio.
  • Qualsiasi utente può avere un pannello preconfezionato da Affidaty, oppure uno custom personalizzato.
  • Qualsiasi utente può utilizzare, in mobilità, alcune funzionalità primarie:
    • per esempio per consultare il proprio profilo, cambiare password, ecc.
  • Qualsiasi utente può cercare un servizio per nome o per categoria.

ABS è, in conclusione, una piattaforma in continua evoluzione ed attualmente composta da una dashboard suddivisa in:

  • Tutti i servizi disponibili;
  • Servizi sottoscritti;
  • Servizi in fase di approvazione.

Questa suddivisione è stata creata esattamente per permettere all’utente di tracciare sia tutti i servizi messi a disposizione su ABS, sia i servizi che ha già ottenuto, che i servizi che stanno per essere approvati sulla propria dashboard.

9.1 Cosa sono


Si tratta di modificatori di stato di una blockchain. Nella pratica, sono degli applicativi che vanno a descrivere in modo deterministico il comportamente di una determinata circostanza.

È possibile, quindi, sviluppare ed utilizzare uno smart contract per regolamentare l’utilizzo delle monete all’interno di un circuito; nel momento in cui ho implementato questo comportamento, la blockchain ha lo scopo di conservarlo e metterlo a disposizione in caso di richiesta di utilizzo.

Come abbiamo visto precedentemente, quando un account viene abbinato ad uno smart contract, questo collegamento non può essere modificato.

Un programma immutabile dà la caratteristica di intermediare un’operazione avendo la certezza che mai nessuno potrà alterarne le regole di gioco. Ovvero: se utente A si accorda con utente B ed assieme decidono di sviluppare uno smart contract in cui user A è il beneficiario delle fees di una determinata operazione, non sarà possibile che altri utenti possano modificarlo. Per tutte le transazioni economiche che passeranno attraverso quello specifico contratto intelligente, una prestabilita percentuale andrà sempre nel wallet dell’utente A. Nessuno, né utente A, né utente B, né nessun altro, potrà modificare il sistema costruito ed implementato.

Quello fatto è solo un esempio, uno spaccato generale della teoria; nella pratica abbiamo applicato questo concetto ed abbiamo utilizzato la tecnologia per creare molti scenari di utilità locale, cioè progetti e prodotti con clienti e partners. Ne vediamo di seguito qualcuno.

Di seguito, analizziamo una carrellata di smart contract di utilità, già presenti in T.R.I.N.C.I..

9.2 Monete Programmabili


9.2.1 Descrizione.

Una moneta programmabile è una moneta che ha regole e comportamenti custom, ovvero un asset che può essere costruito in modo affine ai comportamenti decisi da regole definite a monte.

9.2.2 Esempio

Con gli smart contract si può costruire una moneta che finisce sui conti corrente delle persone seguendo determinate regole:

  • posso creare un conto corrente in cui posso inviare qualsiasi tipo di token, ma per il cui ritiro serva la firma del proprietario del conto stesso;
  • posso, quindi, avere un mio conto corrente e programmare una moneta virtuale che si depositi su quel conto. Per ritirare la moneta dal conto e spostarla sul conto di un’altra persona è necessaria la mia firma, ovvero la mia volontà concreta di eseguire tale operazione.

Nelle banche questa cosa non è proprio così, poiché esse muovono dei soldi dal conto corrente senza l’autorizzazione dell’utente; a volte chiedono una prova per farlo (al fine di non essere accusate di aver mosso del denaro senza l’autorizzazione dell’utente).

Un esempio concreto è il caso in cui l’utente voglia fare un bonifico verso qualcuno: in quel caso l’utente sta chiedendo alla banca di fare quel bonifico e la banca successivamente lo esegue per l’utente. Questa è una cosa ben diversa dall’avere il possesso del proprio conto e mandare volontariamente del denaro a qualcuno. Se la banca non vuole effettuare quell’operazione (per qualsiasi motivo), non la esegue. Se la banca blocca il conto corrente dell’utente (per qualsiasi motivo) il denaro dell’utente rimane dentro quel conto, ma qualunque tentativo dell’utente di avere accesso al proprio denaro e di spostarlo, in quel caso, viene rifiutato.

Nel circuito T.R.I.N.C.I. è possibile costruire una moneta che se è di proprietà dell’utente, l’utente stesso può farne ciò che vuole. Non esiste al mondo nessun soggetto o istituzione (tantomeno Affidaty Blockchain Technology Provider) che possa entrare nei wallet e muovere le monete senza autorizzazione dell’utente.

Questo è il mondo delle monete programmabili. In T.R.I.N.C.I. ho quindi creato una moneta semplice, con la quale posso spostare il denaro quando voglio, ma posso creare anche monete più complesse.

  • posso creare monete che si possano spostare solo se nel wallet (il conto) ci sia una quantità minima di moneta;
  • potrei quindi mettere una soglia e dire “il wallet può raccogliere denaro, ma può spostare denaro solo se esso contiene almeno una soglia minima di 1.000 unità della moneta”;
  • una volta creato, questo comportamento sarà indelebile, quindi nessuno potrà permettere lo spostamento di fondi se il wallet contiene meno di 1.000 unità della moneta;
  • un esempio è lo staking: è possibile creare dei conti che raccolgono monete, ma che sono bloccati volontariamente dall’utente fino ad una certa data. In questo caso è lo smart contract stesso che, superata questa data, permetterà all’utente di muovere i suoi fondi, diversamente l’utente non potrà muoverli.

9.2.3 Per lo sviluppatore

Tutte queste caratteristiche sono implementabili dallo sviluppatore. Quest’ultimo, infatti, potrà costruirle in maniera molto semplice; non tramite una configurazione, ma tramite una programmazione vera e propria.

Successivamente, con l’ottenimento di maggiore esperienza, lo sviluppatore potrà costruire scenari più evoluti, come per esempio abbiamo fatto in T.R.I.N.C.I. con lo Advanced Asset (un modello di moneta programmabile che ha già tutte le caratteristiche necessarie per poter funzionare come la transfer, la pay, la gestione delle fees, la gestione delle witness, eccetera..), inizializzando la sua propria configurazione con i relativi parametri di configurazione come per esempio:

  • per determinare quale sia il beneficiario delle fees,
  • il comportamento da eseguire in caso di uno staking piuttosto che di un’altro,
  • eccetera..

Una volta che una moneta viene inserita in un account, eredita i comportamente dell’advanced asset e li specializza con la configurazione che gli viene data dallo sviluppatore.

Ecco che gli scenari di programmazione che vengono aperti dalla tecnologia T.R.I.N.C.I. fanno da banco da lavoro a vantaggio dei programmatori che avranno una piattaforma di lavoro per espandere competenze ed applicazioni di esse al mondo business: ampliare la creazione di funzionalità aggiuntive per l’Advanced Asset; creare una moneta da zero prendendo magari ispirazione dall’Advanced Asset; creazione di moneta per lo sblocco di dispositivi IoT (esempio: un contatore elettrico smart che ti eroga la corrente solo se paghi il contatore..).

9.2.4 Per l’ azienda

Le aziende hanno un vantaggio in questa circostanza: l’Advanced Asset, da solo, copre probabilmente il 90% delle esigenze necessarie per una azienda che decide di entrare in blockchain.

Qualora ci fossero esigenze aggiuntive, l’Advanced Asset permette addirittura l'estensione di queste caratteristiche, senza necessità di riprogrammarsi esso stesso, come per esempio:

  • gli hook, cioè gli “uncini”, sono 2: “after transfer” e “before transfer”. Sono delle chiamate remote che lo smart contract stesso esegue verso un account per notificargli che gli sono arrivati dei soldi;
  • questi uncini funzionano in maniera molto efficace: potrei avere un comportamento particolare di un token solo in uno specifico wallet. Potrei dire, per esempio, che se ricevo quel token specifico lo invio direttamente a qualcun altro, ciò che in gergo viene definito “Proxy Wallet”.
    • Per fare ciò io non avrò la necessità di riprogrammare tutto l’Advanced Asset, ma mi sarà sufficiente riprogrammare solo il wallet, aggiungendo una funzione che si chiama “After Transfer”, cioè un uncino che verrà richiamato in automatico dall’ Advanced Asset ogni qualvolta riceverò un pagamento;
    • ecco che posso estendere le funzionalità dell’Advanced Asset anche senza modificare il comportamento del wallet.

9.3 Stable and Unstable Coin


9.3.1 Descrizione.

Chi effettua acquisti di token ai fini speculativi ragiona principalmente distinguendo due aspetti:

  1. Stable Coin, cioè un conio ancorato ad una moneta stabile, che può essere l’Euro piuttosto che il Dollaro, ma anche Bitcoin stesso. Questo vuol dire che è l’anchoring alla moneta di riferimento a dover essere stabile: sale Euro e sale il conio, sale Dollaro e sale il conio, sale Bitcoin e sale il conio (e viceversa). In sintesi lo Stablecoin rappresenta un wrapper digitale di una moneta che sta al di fuori della blockchain (in caso di moneta FIAT) o dentro ( in caso di bitcoin);
  2. l’Unstable Coin non ha nessun riferimento con una moneta stabile; nel caso di T.R.I.N.C.I. si riferisce ad un patrimonio costituito da Witness (testimonianze di valori).
    • Il suo prezzo può oscillare perché cambia il suo sottostante: tramite le witness si riesce a certificare che dietro quel token ci sono conti corrente, opere d’arte, valori, quindi si può creare un sottostante a compensazione del numero di monete.
    • Si può lasciare libera circolazione al mercato e l’order book è ciò che determina il prezzo del valore dell’elemento in questione.

Stable ed Unstable sono due scelte molto nette per le grandi diversità dei due ecosistemi, ma non è migliore una rispetto all’altra. Semplicemente una è destinata ad uno specifico settore e l'altra ad un altro.

Esempio: se volessi svolgere una raccolta fondi, dovrei effettuarla necessariamente con uno Stable Coin poiché i fondi raccolti devono diventare il capitale su cui fondare la costruzione di una moneta: se io raccolgo 50 milioni di €, dovrò avere uno Stable Coin dedicato ed ancorato all’Euro che mi permetta di avere 50 milioni di token in corrispondenza dei 50 milioni di euro raccolti.

Investire su uno Stable Coin di per sé non dà nessun valore, poiché uno Stable Coin non ti dà una rendita come invece la può dare un Unstable Coin. Detenere uno Stable Coin generalmente dà l’accesso a godere di diritti all’interno dell’azienda che ha rilasciato il conio, ad esempio: il loro possesso può dare diritto di voto o diritti azionari all’interno di un’azienda.

Con gli Unstable Coin, al contrario, un apprezzamento del progetto legato ad esso può aumentare il valore del conio, o indebolirlo in caso di deprezzamento del progetto.

9.3.2 Stable Coin in T.R.I.N.C.I.

Affidaty, attraverso T.R.I.N.C.I., ha prodotto l’Eurs, uno Stable Coin agganciato all’Euro, quindi tecnicamente Eurs è un wrapper dell’Euro. Eurs è collegato al circuito SEPA, quindi è in grado di fare calcoli al volo delle disponibilità finanziarie dei vari conti corrente che vengono utilizzati da Banche internazionali per garantire il fondo cassa della copertura dell’Euro.

Eurs è in grado di “partorire cloni”, cioè di costruire token che hanno nomi dell’azienda che decide di fare questo tipo di token, garantendo di fatto una cosa interessante. L’utente che opta per la creazione di un clone dell’Eurs può decidere arbitrariamente delle fees da trattenere dalle transazioni. Sostanzialmente, nel suo specifico caso, è come se diventasse un azionista del modello di business dell’Eurs.

Chi ha in mano l’Eurs o un clone dell’Eurs è sicuro di avere un rispettivo controvalore in Euro che può scambiare in millisecondi, ottenendo in cambio i propri fondi in valuta FIAT sul proprio conto corrente bancario, semplicemente scambiando in pochi istanti gli Eurs in Euro.

Questo dà vita a quello che abbiamo chiamato “Effetto Casinò”:

  • entrare in un casinò;
  • cambiare i soldi in fiches;
  • le fiches diventano Eurs o cloni dell’Eurs;
  • esse vengono utilizzate all’interno del casinò;
  • nel nostro caso vengono utilizzate all’interno della blockchain di T.R.I.N.C.I. per fare acquisti, vendere, spostare valori da un wallet all’altro;
  • chiunque poi ritorni al banco del casinò potrà riconvertire le proprie fiches in Euro, senza attendere inutili tempistiche burocratiche o altro;
  • tutto questo poiché il possesso del token rappresenta un controvalore che esiste realmente, che era solo in attesa di essere scaricato.

9.3.3 Vantaggio per le aziende

In un circuito di questa portata, quindi, un'azienda che è nell’ecosistema T.R.I.N.C.I., all’interno del quale ha sviluppato il proprio business, può serenamente entrare in Synkrony Exchange (l’exchange nativo della tecnologia T.R.I.N.C.I.) e può:

  • incassare gli Eurs derivanti dalla vendita dei propri prodotti o servizi;
  • cambiare in seguito gli Eurs in Euro, scaricandoli poi eventualmente e velocemente sui propri conti bancari.

L’enorme vantaggio di cui godono le aziende con un siffatto sistema è certamente quello di avere accesso a clienti che spendono criptomonete per l’acquisto di prodotti e/o servizi. Quello di T.R.I.N.C.I. (con Synkrony Exchange nativo) è un sistema tecnologico che permette a tutti gli attori del mondo blockchain di poter operare in modo completamente compliant con le normative vigenti, sia che si tratti di un’utenza consumer che di un’utenza business.

9.3.4 Vantaggio per gli sviluppatori

Essendo queste delle monete arricchite rispetto all’Euro, T.R.I.N.C.I. produce grandi vantaggi agli sviluppatori. Si parla chiaramente di arricchimento tecnologico. Oggi, il flusso dell’Euro è quello di spostarsi da un conto ad un altro, non è strutturato per fare qualcosa di più. Tutti i sistemi tecnologici attorno ai conti corrente asservono alla creazione e gestione di funzionalità aggiuntive.

Esempio: io invio del denaro dal mio conto a quello dell’Enel per pagare una bolletta: l’Enel attiva i suoi sistemi grazie ai quali, una volta verificato il pagamento, sblocca la bolletta.

Nel caso delle monete programmabili di T.R.I.N.C.I., io posso costruire un sistema sinergico in cui l’invio del denaro a quel determinato wallet esegue il pagamento della bolletta in modo deterministico: nessuno potrà inserirsi nel mezzo della transazione, eseguendo errori di lettura o di trascrizione, facendo poi risultare la bolletta come non pagata.

Quindi il vantaggio per gli sviluppatori è quello di lavorare in un tavolo unico in cui moneta e dati stanno sullo stesso piano.

9.4 Tokens


9.4.1 Descrizione.

Token è l’espressione più generica per determinare un elemento portabile da un asset all’altro: le monete sono token, ma i token non sono necessariamente monete. Un token è una rappresentazione digitale di un valore: se questo valore rappresenta il saldo di un wallet si parla di monete, ma questo valore può non rappresentare necessariamente un saldo di un conto corrente.

Esempio. GoGoFood: abbiamo costruito un circuito di buoni pasto all’interno della blockchain e l’unità del valore di questo token non è il controvalore in Euro del buono pasto, ma è l’unità del singolo buono pasto. Il buono pasto si porta dietro una serie di informazioni:

  • chi lo ha emesso;
  • quanto denaro vale;
  • la data di scadenza;
  • altre informazioni aggiuntive.

Un token è un elemento che contiene tutte queste informazioni e che, in più, può essere spostato da un wallet ad un altro. Quindi, un buono pasto lo posso avere nel mio wallet ma non avrò esclusivamente un numero come accade per le monete in generale (“io ho 5 Eurs/Euro”), bensì avrò:

  • “7 token di tipo buono pasto”;
  • di questi ne voglio spostare 2;
  • i 2 token di buono pasto andranno in un altro wallet;
  • il wallet in cui andranno sarà quello di un ristorante;
  • il ristorante prende questi 2 token buono pasto e li cambia in Euro;
  • il ristorante avrà, infine, degli Euro reali.

Il sistema così costruito non è come gli altri sistemi attualmente esistenti, cioè con una centrale che raccoglie informazioni e le smista.; In T.R.I.N.C.I., infatti, il sistema si basa su uno strumento, il buono pasto, già programmato per agire in un determinato modo: la programmazione è all’interno del buono pasto stesso.

9.4.2 Vantaggio per l’utente azienda.

I token nascono con un’esigenza precisa:

  • ho una esigenza di business;
  • la devo strutturare;
  • se deve essere strutturata in modo classico si deve creare tutta l’infrastruttura hardware (on premis o cloud), quindi si devono implementare i server, gli applicativi, i gestionali, gli elementi di controllo e verifica, eccetera;
  • in blockchain T.R.I.N.C.I., invece, posso costruirmi tutta la logica comportamentale attorno ad un token senza dover costruire dalla A alla Z tutto l’ecosistema attorno. Nel caso dei buoni pasto, per esempio, sarà sufficiente costruire un ecosistema di dashboard di reportistica (mobile o web), al resto penserà la T.R.I.N.C.I. blockchain, permettendo la costruzione dei token ed il loro passaggio da wallet a wallet tramite la tecnologia stessa;
  • utilizzando T.R.I.N.C.I., il 60-70% delle funzionalità complesse spesso possono essere risolte a tavolino con uno smart contract, investendo poi tempo e risorse nella costruzione di siti web e portali mobile a scopo di reportistica o di sistemi dispositivi;
  • in blockchain è necessario che l'applicativo conceda la firma della transazione: in T.R.I.N.C.I. abbiamo un sistema che si chiama Auth-In che è un web component portabile. E’ simile a MetaMask, ma con caratteristiche aggiuntive e senza la necessità di installare alcun software perché scritto in javascript;
  • tecnicamente, per spostare dei buoni pasto da un wallet ad un altro esiste un sistema già costruito che permette la creazione della transazione e la sottomissione di questa all’interno della blockchain;
  • gli applicativi sono per il 95% di lettura delle informazioni, mentre la scrittura avviene tramite un sistema unico che è quello della sottomissione delle transazioni.

9.4.3 Vantaggio per lo sviluppatore.

Il vantaggio di uno sviluppatore, o comunque di chi costruirà l’ecosistema attorno al bisogno di una azienda, sarà quello di utilizzare strumenti facili per costruire sistemi molto complessi che in condizioni normali riescono a muoversi tra “n” applicativi costruiti.

In questo caso, invece, costruendo uno smart contract, lo sviluppatore è in grado di pilotare il comportamento di quello strumento direttamente nello smart contract. Se al di sopra esiste una app mobile, o un sistema front end qualsiasi, non

9.5 NFT


9.5.1 Descrizione.

SmartContracts_1

Gli NFT sono dei token speciali:

  • sono spesso descritti come opere d’arte, ma in realtà non lo sono, nonostante siano divenuti famosi nel mondo come applicativo all’arte (arte digitale);
  • NFT sta per Not Fungible Token, cioè token non fungibili;
  • un token fungibile è un token che se presente in un wallet, può essere spostato secondo le volontà del proprietario del wallet stesso, ad esempio: si hanno 5,00 € nel conto, sono fungibili, quindi vuol dire che si è liberi di spostarli ad una persona terza;
  • un token non fungibile è un token per il quale non basta la volontà affinché sia movimentato, anzi, spesso è ininfluente la volontà del possessore nei confronti dell’NFT stesso (eccezion fatta per il momento in cui gli vengono inviate le configurazioni);
  • immaginiamo un’opera d’arte: classico NFT. Se fosse un fungible token, l’opera d’arte sarebbe nel wallet di Luca e l’unico modo per comprarlo sarebbe dare del denaro a Luca. Luca dovrebbe prendere di sua spontanea volontà l’opera d’arte e trasferirla nel conto di chi ha fatto il pagamento;
  • in questo modo si tornerebbe ad un sistema insubordinato in cui è la volontà dell’utente di trasferire questa opera solo se riceve il pagamento:
    • è quello che succede nella vita reale quando si vende un’automobile;
    • se l’utente 1 effettua il bonifico “forse” l’utente 2 gli cede la macchina;
    • se l’utente 2 ci ripensa, l’utente 1 ha oramai fatto il bonifico, quindi, senza conciliazione, i due utenti sono costretti a seguire le vie legali.
  • Un NFT è invece uno strumento tramite il quale l’utente:
    • è il venditore e può controllare la propria vendita;
    • può impostare un prezzo;
    • può decidere se venderlo o meno;
    • può impostare altre configurazioni aggiuntive nel NFT;
    • ma nel momento in cui ha configurato il NFT, l’utente 2 che vuole acquistare l’NFT stesso invece di inviare il denaro all’utente 1 che lo sta vendendo, lo invia direttamente al NFT;
    • l’NFT ha uno smart contract che nel momento in cui il denaro inviato è sufficiente per coprire il costo della vendita non viene incassato dal NFT, bensì tramite una tecnica di proxy il denaro viene inviato al venditore al netto di una fee (commissione);
    • la fee è di proprietà dell’artista, che sarà quindi remunerato a vita con la commissione, per qualsiasi transazione avvenga su quel NFT;
    • nel frattempo la proprietà dell’opera si sposterà dal wallet del venditore a quello del compratore;
    • Not Fungible, quindi, non significa “che il Token non si sposta”, ma che si sposta in modo non direttamente legato alla volontà dell’utente. Questo, infatti, ha la libertà di dire che il NFT è vendibile e ne stabilisce il prezzo e chiunque spedisca il denaro sufficiente per il NFT, si “aggiudica” il NFT stesso. Tutto questo senza la minima interazione dell’utente per la vendita.

9.5.2 Vantaggio per lo sviluppatore.

Per gli sviluppatori, esistono in T.R.I.N.C.I. dei modelli pre costruiti di NFT. Essi possono essere presi come spunto dagli sviluppatori stessi per la costruzione di altri NFT, oppure possono essere presi così come sono. Quindi, con le dovute configurazioni possono essere usati direttamente.

Costruire un marketplace di NFT non risulta complesso con le configurazioni proposte in T.R.I.N.C.I., diversamente la difficoltà sarà leggermente più elevata solo in relazione alla creazione di regole diverse da quelle già pensate ed introdotte negli NFT da T.R.I.N.C.I..

Quindi, l’utente finale potrà sia usare un marketplace di NFT già costruito con T.R.I.N.C.I., sia un marketplace che uno sviluppatore ha creato da solo, collegato però con il sistema T.R.I.N.C.I..

Affidaty fornisce gli smart contract NFT e da la possibilità agli sviluppatori di creare il proprio conio dedicato (Stable Coin ancorato a EURS), legato agli NFT, permetto loro di crearsi la propria piattaforma aNFT (vedi OpenSea) utilizzando la tecnologia T2 come da flusso tecnico di seguito riportato.

9.6 Deleghe


9.6.1 Descrizione.

Si parla di un applicativo molto richiesto a livello Enterprise poiché quando si comincia a “giocare” con la tecnologia blockchain ci si accorge di alcune circostanze che meritano attenzione.

In qualsiasi blockchain un wallet è di proprietà di una persona sola. L’indirizzo del wallet è legato ad una chiave pubblica che ha una chiave privata, proprio per creare il collegamento biunivoco tra wallet e persona che lo può utilizzare.

  • Scalando a livello Enterprise un’azienda ha un wallet, ma di chi è?
  • Dell’amministratore delegato?
  • Probabilmente è dell’Amministratore Delegato finché è in carica.
  • Nei sistemi classici dove ci si autentica con email e password, la password può essere cambiata. Se l’accesso al conto in banca dell’Amministratore Delegato dovesse - essere rimosso poiché l’AD è cambiato, o si rimuove il profilo utente o se ne modifica la password. In questo modo il precedente utente AD non può più operare nello specifico account.

In blockchain, questa cosa non può funzionare, poiché la chiave privata non la si può cambiare.

  • Questo cosa significa? Che ogni azienda dovrebbe avere 1 account per ogni Amministratore Delegato o per ogni utente che opera sul conto corrente?
  • Ed i fondi disponibili per un Amministratore Delegato?
  • Un domani che lascerà l’azienda saranno disponibili sul suo conto e dovrebbe aver cura di trasferirli verso il conto del nuovo Amministratore Delegato?

Questi sono i maggiori problemi che si incontrano nella costruzione in blockchain dei cosiddetti “Soggetti Plurimi”, cioè di quei soggetti tra i quali deve esserci una collaborazione interna di ruoli per la gestione di un conto unico.

Quello che è stato costruito in T.R.I.N.C.I. è un sistema di deleghe dove tecnicamente si può eleggere una persona (un wallet) con una determinata carica a fare determinati tipi di operazioni su determinati wallet.

9.6.2 Vantaggio per l’utente azienda.

Immaginiamoci ora l’azienda che ha una chiave privata del proprio wallet:

  • non può consegnarla all’amministratore perché non potendola modificare in futuro, non avrà nessuna garanzia che l’AD la cancellerà quando non sarà più Amministratore dell’azienda;
  • per questo motivo l’azienda potrebbe avere sempre il sospetto che tale utente (ex AD), ad esempio tra 10 anni, possa entrare nel wallet e prelevare tutti i fondi presenti.

9.6.3 T.R.I.N.C.I. ha creato l’alternativa.

  • La chiave privata del wallet viene conservata dall’azienda;
  • grazie a questa chiave si producono deleghe per permettere temporaneamente a certi tipi di soggetti di operare sul wallet;
  • con la stessa chiave si può successivamente rimuovere la delega.

Ecco che un’azienda che ha un wallet unico con dentro “N” fondi, “N” token ed “N” NFT può concedere la delega di operare su:

  • specifici token ad una specifica persona,
  • specifici fondi ad una specifica persona,
  • specifici NFT ad una specifica persona,
  • eccetera..

Tutto questo sistema di deleghe viene reso operativo tramite dei certificati, facilmente costruibili in T.R.I.N.C.I. tramite delle librerie messe a disposizione, nelle quali si identifica il ruolo e le “Capabilities”, cioè ciò che può fare uno specifico operatore su wallets e fondi specifici.

Questo rende più versatile l’utilizzo di un wallet da parte di più persone che devono insistere su più dati. Senza le deleghe avrebbero dovuto condividere la chiave privata aziendale, perdendo di fatto la corrispondenza 1:1 tra wallet e persona.

Sia il problema che la soluzione prodotta da T.R.I.N.C.I. vivono all’interno dell’ambito legale-giuridico, poiché se la chiave privata è in mano ad una sola persona, qualunque operazione venga svolta con quella chiave si può legare deterministicamente a quella persona. Quando la private key è in possesso di più persone si perde questo rapporto e quindi un tentativo fraudolento dell’utilizzo della chiave privata non può essere necessariamente attribuito ad una singola persona responsabile.

9.7 Sistema di voto


9.7.1. Descrizione.

In T.R.I.N.C.I. è stato qui modellizzato un sistema di voto in blockchain, creando uno standard per le DAO (che vedremo successivamente).

Chiaramente, pur essendo di produzione “from scratch” di T.R.I.N.C.I., non è l’unica produzione di sistema di voto possibile. In T.R.I.N.C.I., infatti, gli sviluppatori possono lavorare con la tecnologia proposta per produrre un sistema di voto proprio.

Quello costruito in T.R.I.N.C.I. è un sistema di voto dove è presente una gerarchia di persone che possono creare un ballottaggio con tutta una serie di caratteristiche:

  • Vero o Falso;
  • Si o No;
  • scelta multipla;
  • scelta singola a partire da un elenco;
  • e molte altre

Non si parla di un sistema basico in stile “Vota: Si/No”. Bensì di un sistema complesso comprendente la scelta di candidati come per esempio la scelta in una lista dove devono esserci 5 candidati e deve essere scelto obbligatoriamente 1 oppure “1, massimo 3” e molti altri setup configurabili.

Si determina poi il quorum, la validità della votazione; quindi, il sistema di votazione permette agli utenti di sottomettere voti con la firma per costruire una pool di voti. Quest’ultima finisce il suo mestiere con un trigger, inviando un hook ad un altro smart contract che viene costruito durante la configurazione.

A votazione terminata, tutta la votazione viene trasferita come dati verso un altro wallet; quest’ultimo, alla ricezione farà determinate azioni.

Da aggiungere che in T.R.I.N.C.I. è stata costruita una tecnologia proprietaria molto complessa per creare voti anonimi: essa rende possibile che un certo numero di persone ben identificate possano immettere un voto in maniera anonima, disaccoppiando il voto dalla persona. Con questa tecnologia si riesce a garantire che:

  • solo i votanti che fin dall’inizio erano previsti nella votazione possano sottomettere il voto;
  • che ogni votante possa votare solo una volta;
  • è impossibile sia matematicamente che tecnicamente ricondurre il voto alla persona che lo ha sottomesso.

Riassumendo:

  • l’utente accede con 4RYA (sistema riconoscimento ID);
  • l’utente successivamente sottomente il voto e lo firma;
  • viene riconosciuto a sistema il voto sottomesso;
  • nessuno può vedere che abbia effettuato quel voto.

9.8 DAO


9.8.1 Descrizione.

La DAO è l’evoluzione del sistema di voto: esso infatti è un sistema fine a sé stesso poiché non si entra in merito a quella che sarà la votazione. Potrebbe essere anche una votazione per fini informativi, es.: si vuole chiedere un parere alla community; essa vota ed un singolo ne legge il parere.

Di per sé, la votazione di base non scatena un’azione.

La DAO, invece, è uno smart contract che va a “battezzare” un wallet; è un sistema che permette alla community di utenti di entrare ed uscire da essa secondo regole che sono personalizzabili:

  • basta possedere dei token per far parte di quella determinata DAO;
  • il wallet della DAO può contenere dei token e/o dei fondi;
  • la decisione di spostare questi fondi è demandata ad una elezione;
  • si costruisce una votazione per muovere questi fondi;
  • se si raggiunge il quorum sarà il wallet stesso a firmare la transazione che permetterà ai fondi di venire spostati.

Non è assolutamente necessario che esista un utente esterno che faccia l’operazione manualmente. Può essere a tutti gli effetti descritta come un’organizzazione democratica decentralizzata: le regole di questa organizzazione decentralizzata vengono scelte da chi decide di costruirsi la sua DAO.

9.9 Notarizzazione


9.9.1 Descrizione.

Nella blockchain T.R.I.N.C.I. è possibile ospitare la certificazione di dati. Nelle classiche blockchain si esegue ciò depositando l’hash del dato poiché i dati sono grandi e quindi non ha senso spostare decine di mega in blockchain, visti i costi proibitivi di tale operazione.

In T.R.I.N.C.I., esistendo delle HDSB, è possibile costruire modelli che permettano di ospitare anche grandi quantità di dati: questo permette di notarizzare sia dati che informazioni certificando o l’hash o il documento di dati intero.

In T.R.I.N.C.I. stiamo per produrre, per esempio, la versione con il plugin per il PFS; abbiamo la possibilità di utilizzare una base dati basata su file system gigantesca senza andare ad impattare sulla quantità di dati che finiscono nel blocco fisico della blockchain.

Questo ci porta ad un passo dall’avere una blockchain T.R.I.N.C.I. di notarizzazione in cui si può:

  • consegnare il documento da notarizzare (e che quindi faccia da conservatore del documento) ed in automatico il sistema fa l’hash del documento e salva in blockchain solo l’hash;
  • dall’hash si può anche risalire al documento.

Nelle blockchain classiche di notarizzazione tipo Ethereum, non si può risalire al documento dall’hash. Se sono in possesso del documento posso verificare che il suo hash corrisponda all’hash di notarizzazione, risultando essere una notarizzazione parziale.

Tutto questo a vantaggio chiaramente degli utenti di base, ma anche di professionisti ed aziende che ad oggi necessitano di un servizio di questa portata.

9.10 Filiera Supply Chain


9.10.1 Descrizione.

È la classica catena di notarizzazione per esempio di una filiera produttiva. Tale notarizzazione può esser fatta in maniera classica, cioè conservando in loco la documentazione, notarizzando solo i passaggi del sistema che vengono fatti, oppure utilizzando i sistemi di notarizzazione si può notarizzare direttamente i documenti, ma in più si può creare lo smart contract che certifica la filiera produttiva permettendo di evitare che si possa passare, per esempio, dallo step 2 allo step 4 saltando il 3.

In questo caso, per esempio, la procedura verrebbe rifiutata proprio perché è stata saltato uno step.

9.11 Service Smart Contract


9.11.1 Descrizione.

Il service smart contract è di fondamentale importanza in T.R.I.N.C.I.. A differenza di altri smart contract che sono opzionali oppure sono a carico della fantasia del programmatore, il service smart contract è in qualche modo l’anima che sostiene la blockchain.

È chiamato anche smart contract di bootstrap poiché ha molte caratteristiche: esso è il primo smart contract che viene collocato all’interno di qualsiasi HDSB. Al suo interno, infatti, sono presenti tutte le funzioni che vanno a regolamentare come questa HDSB dovrà funzionare.

Ci sono quindi funzioni ben precise che devono avere quel nome preciso. Il comportamento è a discrezione di chi sviluppa il service smart contract, ma ha delle funzioni precise, un’interfaccia ben precisa. Questa interfaccia permette allo sviluppatore di: decidere se e quanto far pagare per le transazioni; se, ed in che modo, portare all’interno del sistema nuovi smart contract; determinare alcuni comportamenti relativi al controllo delle fees che vengono distribuite durante gli spostamenti.

Questo è uno smart contract che normalmente viene costruito come qualunque altro smart contract: compilato in WASM; depositato nella cartella del nodo.

Immaginiamoci un nodo vergine: quando un nodo parte, un nodo vergine appena scaricato da GitHub, la prima cosa che fa è controllare che esista un database. Ovviamente, essendo vergine, avrà un database vuoto: in biologia sarebbe definito come una cellula staminale, cioè che ha tutte le caratteristiche per diventare più o meno qualsiasi cosa poiché ha tutto il bagaglio di ingredienti per diventare ciò che vuole, ma non ha ancora una specializzazione.

Quando un nodo viene avviato per la prima volta, esso potrebbe diventare qualunque HDSB (Alfa, Beta, Gamma), ma ancora non ha una sua specializzazione, non sa qual è il suo destino, perché ha il proprio database “ancora da determinare”, poiché vuoto.

Quindi il nodo va a cercare questo bootstrap, lo carica e da quel momento comincia a conoscere una serie di informazioni:

  • l’hash del bootstrap, cioè l’hash del file fisico bootstrap.wasm, che potrebbe essere specifico di una particolare HDSB. L’hash è univoco e rappresenta la chiave univoca della rete a cui questa blockchain si sottomette;
  • questo significa che 2 bootstrap uguali in 2 parti diverse del mondo costituiscono un anello di una blockchain;
  • 2 nodi uno accanto all’altro con 2 bootstrap diversi saranno 2 blockchain HDSB diverse che non si parlano, non si vedono, non interagiscono;
  • quindi il service account contiene questo bootstrap e se qualcuno ne cambia anche solo una virgola, va a modificare il comportamento deterministico di quella blockchain;
  • ripetiamo: 2 blockchain con lo stesso bootstrap sono la stessa blockchain, mentre 2 nodi con 2 bootstrap diversi sono 2 blockchain diverse.

10.1 Cos’è

Nel capitolo 8.6.5 abbiamo parlato in modo approfondito dell’algoritmo di consenso e distribuzione, ma abbiamo deciso di dedicare questo capitolo per trattare dell’argomento in modo più descrittivo, con l’obiettivo di far capire al lettore i motivi e le sfide che hanno portato Affidaty a creare un algoritmo di consenso e distribuzione dedicato a T.R.I.N.C.I.

Per T.R.I.N.C.I., Affidaty, ha dovuto sviluppare un proprio algoritmo di consenso non ereditato da altre blockchain, questo perché le tante innovazioni che ha portato, le tante novità costruite (ad esempio l’Eurs ed il BitBël) sono vere e proprie soluzioni disruptive che non esistevano (e non esistono) in altri ambienti.

Questo ha costretto Affidaty a lavorare ad un algoritmo di consenso che è risultato realmente più efficiente di tanti altri, Proof Of Work in primis: non sono stati usati sistemi tecnologici energivori sia per scelte etiche attorno al consumo energetico, sia per scelte tecnologiche e di business.

L’algoritmo di consenso è come il motore di una vettura, quindi è fondamentale capire l’obiettivo da raggiungere per poi calibrarlo finemente in relazione allo scopo. Il ruolo fondamentale di un algoritmo di consenso in blockchain è “cercare di garantire vita eterna alla tecnologia blockchain stessa” (tecnicamente un algoritmo di consenso è uno strumento necessario ad allineare e coordinare un sistema distribuito).

Nelle blockchain private esiste un modo molto semplice per creare un algoritmo di consenso: definire chi sono i Miners, i validatori. Un'implementazione statica come quella sopra illustrata però non è fault tolerant ed inoltre nel caso in cui l’azienda dietro all'infrastruttura decidesse di abbandonare il progetto lascerebbe gli utenti alla loro sorte causando probabilmente grosse perdite.

In Bitcoin esiste un algoritmo di consenso preciso, secondo il quale in un determinato tempo e modo i computers si auto coordinano per eleggere un leader ogni volta che è necessario: se oggi la rete di BitCoin fosse composta da 1.000 nodi, essi si organizzerebbero per trovare un leader ogni 10 minuti per portare avanti la blockchain. Tra 1.000 anni questi 1.000 nodi saranno tutti distrutti, ce ne saranno altri. Nel tempo, mano a mano che i nodi vecchi muoiono e quelli nuovi nascono c’è continuamente una elezione costante del nuovo leader che farà sì che da qui a 1.000 anni esisterà sempre un leader “fresco” per portare avanti il tutto.

L’algoritmo creato da Affidaty fa proprio questo: garantisce tutte le caratteristiche che abbiamo costruito all’interno della tecnologia, effettua un coordinamento molto efficiente tramite RAFT (algoritmo di distribuzione di classe Enterprise molto proficuo che viene generalmente usato per allineare tecnicamente i sistemi distribuiti) come principio di distribuzione.

RAFT non ha però nulla a che vedere con la distribuzione dei profitti: non è stato costruito per distribuire monete, bensì per far sì che tanti computers sparsi per il mondo lavorassero in concerto pur avendo delay di tempo legati alla rete e legati alla propria potenza di elaborazione intrinseca.

La blockchain può distribuire anche profitti. Affidaty ha modificato RAFT non aggiungendogli caratteristiche, bensì dividendo in 2 la validazione del blocco: uno strato dedicato alla validazione tecnica; uno strato dedicato alla distribuzione dei profitti delle singole transazioni.

Questo algoritmo è un prodotto molto complesso ed altrettanto sperimentale, che però ha prodotto risultati realmente importanti dal punto di vista della statistica dell’utilizzo.

10.2 Come funziona

Il problema della distribuzione è un argomento complesso. Dividere piccole quantità tra un numero elevato di riceventi fa sorgere aspetti non triviali. Si prenda in esempio una transazione per il pagamento di un bene da 1,00 €;

  • essa produce una commissione di 0,10 €;
  • si deve dividere i 0,10 € fra 1.000 persone alle quali spetta una porzione di questa commissione poiché hanno lavorato alla transazione;
  • nella circostanza di un piccolo pagamento, per spostare 1,00 € da Utente A ad Utente B verranno coinvolte 1.000 persone per la divisione del pagamento;
  • tutto questo si trasforma in inefficienza, poiché le 1.000 persone sono tecnicamente 1.000 record in un database e le transazioni devono essere scritte, aggiornate, propagate su tutti i nodi della rete;
  • capirete che il sistema sopra descritto è molto lento;
  • in altre circostanze si possono creare degli accumulatori dove invece di andare a distribuire subito questi 10 centesimi possono essere accumulati ed in seguito distribuiti quando il salvadanaio è un po’ più grande.Questo processo in blockchain è molto complesso da svolgere poiché la questione del tempo è anomala, ovvero, se aspetto 1 mese di accumulo anomala potrebbe accadere qualsiasi cosa come per esempio il cambio degli stakers in gioco; i calcoli cambierebbero e quindi costerebbero.

In Affidaty abbiamo costruito un sistema efficiente che risolve i problemi sopra esposti, difficile da accettare perché è controintuitivo, ma sulla carta si dimostra efficace nella distribuzione dei profitti in relazione alla percentuale degli stakers.

Quello che realmente fa è selezionare dei candidati ai quali inviare totalmente tutto il guadagno. Ciò viene fatto con un’alta frequenza e selezionando i candidati con una probabilità proporzionale al numero di monete che hanno in stake. Quindi è come se si dovessero dividere 10 centesimi: non vengono divisi ma viene trovato un minatore e gli vengono dati tutti e 10 i centesimi. La probabilità attraverso la quale questo minatore è stato selezionato è legata a quante monete ha lui rispetto a tutti gli altri.

Quindi se i minatori avessero tutti il 10% dello stake, su tanti pagamenti da 0,10 €, la probabilità di distribuzione è perfettamente causale: i primi 10 centesimi vanno ad uno, poi vanno ad un altro, poi vanno ad un altro ancora e così via. L’analisi del sistema dimostra che la distribuzione avviene in maniera equilibrata.

Se esiste una distanza di staking (ovvero ci sono utenti che hanno il 3% o il 10% o il 30% o il 5 % e così via), alla fine il sistema permette di garantire che la probabilità con la quale vengono distribuite queste fees cerca di essere in linea. “Cerca” perché sono stati inseriti dei sistemi di causalità voluti con la quale si può dimostrare sulla carta che io, nonostante abbia una piccola parte di staking, posso ottenere grandi guadagni. Il sistema ragiona in questo modo: una grande transazione che per esempio produce 50,00 € di commissione può capitare anche ad un utente che magari ha pochi centesimi di monete in staking. È poco probabile ma può succedere Nella stessa misura in cui chi ha una tessera sola può ambire a vincere la tombola intera: sicuramente la probabilità che vinca sarà più bassa di chi ha comprato 50 tessere, ma non è nulla.

Con questo sistema, i grandi investitori, giocando sui grandi numeri, hanno una garanzia di guadagni costanti proprio perché basandosi sulla legge dei grandi numeri. D’altro canto il piccolo investitore può, in maniera del tutto stocastica, puntare ad ottenere grandi guadagni sulla base della selezione all’interno del sistema.

L’algoritmo in questione si chiama POP, cioè Proof Of Play: se un utente è un minatore ed è attivo (ovvero tiene acceso e funzionante costantemente il nodo per la blockchain), può concorrere all’ottenimento dell’incentivo. Diversamente, se non è attivo o lo è a tratti, non partecipando attivamente alla rete, non potrà far parte degli utenti minatori che possono essere selezionati per ottenere l’incentivo tramite la POP.

11.1 Architettura del Core


11.1.1 - Preambolo

L'ambizione di T.R.I.N.C.I. è quella di fornire un framework blockchain flessibile ma efficiente per costruire un nodo in grado di eseguire qualsiasi applicazione specifica per le logiche di business.

È un progetto ambizioso perché:

  • è stato sviluppato da zero;
  • introduce alcune caratteristiche innovative non riscontrabili in nessun grande progetto;
  • fornisce un meccanismo di consenso flessibile e un ambiente di smart contracts.

11.1.2 - Componenti del Core

  • Archiviazione: archiviazione blockchain persistente che utilizza l'archiviazione chiave-valore orientata alle prestazioni.
  • Comunicazione: comunicazione tra nodi tramite protocollo p2p, pub/sub, req/res e gossip.
  • Consenso: flessibile e specifico per ambito (PoA o PoW).
  • Ancoraggio: servizio opzionale per eseguire ancoraggi su altre catene stabili.
  • Smart Contracts Execution: sandbox a prova di errore per eseguire smart-contract molto specializzati e capacità di implementare librerie condivise.
  • SDK: librerie per consentire l'implementazione di smart contract utilizzando i linguaggi di programmazione più diffusi.
  • Canali di comunicazione flessibili: lato client può comunicare con la blockchain utilizzando diversi canali di comunicazione (http-rest, socket tcp raw, custom).

11.1.3 - Struttura dei Blocchi

Un blocco viene notarizzato nel libro mastro della blockchain in modo molto efficiente e compatto al fine di ottimizzare lo storage e il traffico di rete.

Un blocco riassume:

  • Transazioni contenute all'interno del blocco.
  • Incassi generati dalle transazioni del blocco.
  • Stato Account utente dopo l'esecuzione di transazioni di blocco.
  • Hash blocco precedente.

Le strutture consentono di generare in modo efficiente prove di presenza sia per le transazioni che per gli incassi.

11.1.4 - Dalle Transazioni ai Blocchi

Innanzitutto è importante chiarire che dal punto di vista applicativo la blockchain rappresenta un archivio chiave-valore.

Tutte le complessità e i meccanismi interni sono opachi rispetto l'esperienza dell'utente.

L'unica differenza tra un normale database e la blockchain è che l'esecuzione degli smart contract evocati dalle transazioni, che causano la variazione dei valori del database, è asincrona e l'algoritmo di consenso alla base del sistema gestisce la validazioni delle transazioni stesse.

Pertanto, al momento dell'invio della transazione, l'utente può solo sapere se la transazione è stata accettata dalla blockchain per l'esecuzione (transazione non confermata) ma l'esecuzione delle azioni viene posticipata sino alla costruzione di un blocco che contiene la transazione in questione..

11.1.4.1 Transazioni

Una transazione esprime la volontà del suo mittente di eseguire un'azione su uno o più account.

Una transazione, quando eseguita, evoca una delle funzionalità di uno smart contract, .Lo smart contract è un modulo aggiuntivo alla blockchain, sviluppato per estendere le sue funzionalità, in base ai requisiti di progetti esterni che ne sfruttano l’infrastruttura..

Le transazioni vengono eseguite in modo asincrono e il ritardo di compensazione, ovvero l'intervallo tra la generazione della transazione e la sua inclusione in un blocco, dipende da come viene costruito un blocco, quindi dall’algoritmo di consenso usato..

Il core blockchain è indipendente dalla logica aziendale specifica dell'applicazione e le sue azioni sono limitate ai controlli di integrità del formato delle transazioni, alla verifica della firma digitale del mittente e alla propagazione nella rete.

11.1.4.1 Blocchi

Un blocco è una sequenza di transazioni che devono essere eseguite nello stesso ordine dai nodi che fanno parte della blockchain. Un blocco modifica la memoria del database chiave-valore.

Dal punto di vista dell'utente, un blocco può essere pensato come una patch atomica che dovrebbe essere applicata all'archiviazione del database chiave-valore.

Le transazioni all'interno di un blocco vengono ordinate e verificate prima di essere aggiunte ad un blocco.

Le transazioni ritenute valide dal core, ma che per alcuni motivi vengono rifiutate dallo smart contract, rientrano comunque nel blocco. Le loro azioni (cioè le modifiche al database) non vengono confermate ma viene generata una ricevuta con la causa dell'errore.

11.1.4.2 La vita della Transazione dalla genesi al blocco

  • Una transazione viene costruita e firmata dall'applicazione utente.
  • La transazione viene ricevuta dal nodo tramite uno dei canali di input blockchain esposti (es. servizio REST).
  • Viene verificata la validità di una transazione: formato del messaggio, verifica della firma digitale e protezione anti-riproduzione.
  • Un feedback viene immediatamente restituito al mittente. In caso di successo viene effettuato l’hash della transazione. In caso di errore, viene veicolato un messaggio con il motivo dell'errore.
  • In caso di fallimento, il viaggio della transazione si ferma qui.
  • Una transazione ricevuta da un nodo viene propagata a tutti i nodi di rete tramite protocollo gossip.
  • Le transazioni non confermate vengono mantenute nell’apposita coda in attesa di essere incluse in un nuovo blocco.
  • Viene creato e proposto un nuovo blocco dal leader scelto tramite algoritmo di consenso se una di queste due condizioni è soddisfatta:
    • viene raggiunta la soglia di transazioni per blocco,
    • scatta il timeout del blocco.
  • Quando un nodo riceve un blocco se questo non è il blocco previsto inizia la procedura di allineamento.
  • Quando le transazioni all'interno di un blocco vengono confermate, il blocco viene inserito all'interno della blockchain e le modifiche vengono applicate atomicamente.

11.1.4.3 Risultati Asincroni

Le transazioni sono asincrone, il che significa che al mittente della transazione non viene fornita una risposta immediata come risultato dell'esecuzione della transazione. La notifica sincrona è impossibile a causa del funzionamento del consenso nelle blockchain.

Una volta che una transazione è stata inviata con successo, l'utente possiede quello che viene comunemente chiamato ticket (cioè l'hash della transazione).

Il mittente può recuperare lo stato di esecuzione utilizzando due metodi: basato su interrupt o su polling.

  • interrupt: il nodo dà all'applicazione la possibilità di sottoscriversi ad eventi di interesse. In particolare, l'applicazione può sottoscrivere eventi che indicano la creazione di nuovi blocchi. Una volta ricevuto un evento di creazione di un blocco, il mittente può verificare se la transazione che stava aspettando è stata inclusa in quel blocco utilizzando il ticket di transazione.
  • polling: l'applicazione esegue il polling sul nodo utilizzando il ticket di transazione chiedendo in risposta la ricevuta. I tempi di polling dipendono dalla configurazione del nodo, ma in genere sono una questione di secondi.

11.1.4.4 Transazioni Fallite

L'esecuzione di contratti intelligenti potrebbe non riuscire. Il formato degli errori è definito dallo smart contract stesso (specifico dell'applicazione). Il DB contiene sia le transazioni riuscite che quelle non andate a buon fine a condizione che i validatori siano d'accordo sullo stesso risultato.

La registrazione viene fornita per consentire a client leggeri di verificare lo stato di esecuzione.

A livello di smart contract ci sono due categorie di registrazione:

  • log locali: inoltrati al node logger,
  • emit events: inoltrato al servizio bridge per essere eventualmente inoltrato a componenti esterni (es. applicazione utente).

11.2 Identificatore Account


11.2.1 Intro

Ogni account utente ha un identificatore generato in funzione della PublicKey dell'utente utilizzando la seguente formula:

AccountId = Base58 ( MultihashHeader | SHA256 ( ProtobufHeader | ASN1Header | DecompressedRawPublicKey  )  )

Proprietà:

  • legato alla chiave pubblica del titolare dell'account.
  • generato tramite un algoritmo hash crittograficamente sicuro con collisione proprietà di resistenza.
  • breve ed è facilmente scambiabile tra utenti blockchain.
  • a prova di futuro poiché lascia aperta l'opportunità di aggiornare l'algoritmo (agilità di protocollo).
  • allineato al libp2p Metodo di generazione PeerId.

11.2.2 Procedura per la chiave ECDSA

Chiave pubblica decompressa grezza:

    04 (decompressed form)
    X: 5936d631b849bb5760bcf62e0d1261b6b6e227dc0a3892cbeec91be069aaa25996f276b271c2c53cba4be96d67edcadd
    Y: 66b793456290609102d5401f413cd1b5f4130b9cfaa68d30d0d25c3704cb72734cd32064365ff7042f5a3eee09b06cc1

Anteponi l'intestazione ASN.1 (come definito dallo standard x509)

    30 76   // strucure (bytes count = 118)
      30 10   // structure (bytes len = 16)
        06072a8648ce3d0201      // EC public key OID
        06052b81040022         // secp384r1 curve OID
      03 62 00  // bitstring (bytes count = 98)
        04
        5936d631b849bb5760bcf62e0d1261b6b6e227dc0a3892cbeec91be069aaa25996f276b271c2c53cba4be96d67edcadd
        66b793456290609102d5401f413cd1b5f4130b9cfaa68d30d0d25c3704cb72734cd32064365ff7042f5a3eee09b06cc1

Anteponi intestazione Protobuf (come definito da libp2p)2p)

    08 03  // Algorithm type identifier (ECDSA)
    12 78  // Content Length
      3076301006072a8648ce3d020106052b81040022036200
      04
      5936d631b849bb5760bcf62e0d1261b6b6e227dc0a3892cbeec91be069aaa25996f276b271c2c53cba4be96d67edcadd
      66b793456290609102d5401f413cd1b5f4130b9cfaa68d30d0d25c3704cb72734cd32064365ff7042f5a3eee09b06cc1

Calcola lo SHA256 del buffer complessivo

    sha = SHA256(buffer)
    sha = 93d8a1e44a9d179238b598458f5293666890e8c0fcec0cce682522398d726dd5

Anteponi l'intestazione "multihash" allo sha risultante.

    12      // hash algorithm identifier (0x12 = SHA256)
    20      // hash length (0x20 = 32)
    93d8a1e44a9d179238b598458f5293666890e8c0fcec0cce682522398d726dd5

Risultato finale in base58

    AccountId = "QmYHnEQLdf5h7KYbjFPuHSRk2SPgdXrJWFh5W696HPfq7i"

11.2.3 Dettagli Multihash

Aggiunge all'hash puro una breve intestazione con l'identificatore e la lunghezza dell'algoritmo.

Reference https://github.com/multiformats/multihash

11.3 Formato Transazione


11.3.1 Schema

  {
    "data": {
        "account": string,
        "nonce": bytes,
        "network": string,
        "contract": bytes,
        "method": string,
        "caller": {
          "type": string,
          "curve": string,
          "value": bytes,
        },
        "args": bytes,
    },
    "signature": bytes
  }
  • account: identificatore dell'account di destinazione (come definito here). Questo è l'account su cui verrà eseguito il metodo di contratto richiamato.

  • nonce: valore pseudo-casuale per la protezione anti-riproduzione. Consente di ottenere un hash diverso per le transazioni con lo stesso carico utile.

  • network: nome della rete blockchain. Blockchain con nomi diversi sono incompatibili. Ogni nodo è configurato per funzionare su una rete specifica.

  • contract: identificatore di smart contract definito come contrattowasm multihash.

  • method: nome della funzione dello smart contract da eseguire.

  • caller: identità del mittente della transazione utilizzata per la verifica della firma digitale e (facoltativamente) utilizzata dagli smart contract per prendere decisioni specifiche dell'applicazione:

    • type: identificatore dell'algoritmo di firma digitale (e.g. "ecdsa").
    • curve: identificatore della curva ecdsa (e.g. "secp284r1").
    • value: valore della chiave pubblica.
  • args: argomentazioni specifiche per smart contract. Queste informazioni sono opache al core e vengono trasmesse "così com'è" allo smart contract. Può essere qualsiasi cosa ed è un dovere di smart contract decodificare il contenuto nel modo che meglio si adatta all'applicazione (pacchetto di messaggi per impostazione predefinita).

  • signature: firma digitale del campo dati compresso del messaggio. Verificato utilizzando la chiave pubblica contenuta nel campo data stesso.

11.3.2 Esempio:

  {
    "data": {
      "account": "QmYHnEQLdf5....SPgdXrJWFh5W696HPfq7i",
      "nonce": 0102030405060708,
      "network": "skynet",
      "contract": 12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f9...,
      "method": "terminate",
      "caller": {
        "type": "ecdsa",
        "curve": "secp384r1",
        "value": 045936d631b849bb5760bcf62e0d1261b6b6e227dc0a389...
      },
      args: 82a46e616d65a4436f6c65a5656d61696cb263727573746e3440746f706c...
    },
    "signature": 69bc880acdab862ebbf776b5411b04b5e872369d3b40ca448832...
  }

11.3.3 Serializzazione dei dati

Le strutture delle transazioni sono codificate utilizzando il formato binario [MessagePack] (https://msgpack.org).

Entrambi i formati di serializzazione anonymous e named sono supportati dal core durante la convalida della transazione.

Quando si utilizza il formato anonimo, l'ordine dei campi è importante.

Quando si utilizza il formato denominato, l'ordine dei campi non è importante. In ogni caso, per ottenere le migliori prestazioni durante la fase di deserializzazione, è buona norma organizzare i campi nello stesso ordine descritto da questo documento.

11.3.4 Firma digitale dei dati

Steps:

  1. Il campo data viene serializzato come un array di byte.

    data_bytes = msgpack.serialize(data);

  2. I byte sono firmati digitalmente utilizzando la chiave privata del mittente.

    signature = ecdsa-sign(submitter-private-key, data_bytes);

  3. Il campo firma è aggiunto alla struttura precedente:

  transaction {
    "data": {
      ...
    },
    "signature": ...
  }
  1. La struttura complessiva della transazione viene serializzata utilizzando il formato MessagePack.

    tx_bytes = msgpack.serialize(transaction);

  2. I byte della transazione (tx_bytes) vengono infine inviati al nodo blockchain.

Importante: se la firma digitale è stata prodotta utilizzando un formato di serializzazione (anonimo o denominato), lo stesso formato sarà utilizzato durante la serializzazione della transazione complessiva per l'invio principale.

11.4 Messaggi Blockchain


11.4.1 Intro

Definizione del messaggio utilizzata per la comunicazione con il servizio blockchain utilizzando il canale esposto dal servizio blockchain. Questo formato è utilizzato da tutti i componenti che richiedono una qualche forma di comunicazione con la blockchain. Entrambi i componenti strettamente interni come il componente bootstrap del nodo e il tracer e tutti i componenti che forniscono un'interfaccia al mondo esterno come p2p, bridge, rest services utilizzano questo formato di messaggio. La struttura dei messaggi è data in un formato pseudo json/asn1/rustacean. Quando la serializzazione e la deserializzazione devono essere eseguite dal servizio blockchain, il mittente deve impacchettare la struttura utilizzando il formato anonimo "MessagePack".

11.4.2 Definizioni delle strutture di supporto

CHOICE: è possibile selezionare un solo elemento dall'insieme indicato.

FLAG : più elementi possono essere selezionati dall'insieme dato.

SequenceOf : un array di elementi omogenei.

ByteBuffer := SequenceDi u8

Ticket := MultiHash(MessagePack(Transazione::Dati))

11.4.3 Messaggio Blockchain

Un messaggio che può essere consumato e prodotto dal servizio blockchain.

Message { type: u8, body: MessageBody, }

Tipi di corpo del messaggio insieme ai valori dei tag di tipo utilizzati per la serializzazione:

MessageBody : CHOICE { Exception = 0, Subscribe = 1, Unsubscribe = 2, PutTransactionRequest = 3, PutTransactionResponse = 4, GetTransactionRequest = 5, GetTransactionResponse = 6, GetReceiptRequest = 7, GetReceiptResponse = 8, GetBlockRequest = 9, GetBlockResponse = 10, GetAccountRequest = 11, GetAccountResponse = 12, Stop = 254, Packed = 255, }

Il corpo del messaggio è "appiattito" nella struttura del messaggio, il che significa che non deve essere applicato alcun livello di nidificazione aggiuntivo. Ad esempio, un messaggio di sottoscrizione viene serializzato in quanto definito come:

Message { type: 1, id: String, event: Event, packed: bool, }

Messaggio “Stop”. È un messaggio speciale per fermare il servizio blockchain. Come decisione progettuale, per impedire ai componenti esterni di interrompere il servizio blockchain, questo messaggio viene accettato solo quando proviene da un componente interno. Si presume che solo i messaggi compressi provengano da un componente esterno.

11.4.4 Subscribe

Consiste nella sottoscrizione agli eventi della blockchain T.R.I.N.C.I. Tale sottoscrizione permette di ricevere i messaggi già impacchettati. Questa opzione può essere utile per servizi di inoltro come p2p e bridge.

Subscribe { id: String, // Subscriber id event: Event, // Bitflags with events we want start receiving packed: bool, // Receive already packed data (MessagePack) }

Event : FLAG { Transaction, // receive a GetTransactionResponse when a new (good) tx is received Block, // receive a GetBlockResponse when a block is generated Request, // receive any request that the blockchain is trying to send out }

11.4.5 Unsubscribe

Unsubscribe agli eventi della blockchains.

Unsubscribe { id: String, // Subscriber id event: Event, // Bitflags with events we want stop receiving }

11.4.6 Put transaction

Invia una nuova transazione. La richiesta può essere confermata o meno. Quando viene richiesta la conferma, il servizio blockchain invierà una risposta contenente il risultato di invio corrispondente alla transazione. In caso di successo, il risultato dell'invio è il ticket della transazione (hash). In caso di errore, il risultato contiene il motivo dell'errore come stringa.

PutTransactionRequest { confirmed: bool, // If we require a confirmation tx: Transaction }

PutTransactionResponse { hash: Ticket }

11.4.7 Get Transaction

Ottieni una transazione con un ticket di transazione.

GetTransactionRequest { hash: Ticket }

GetTransactionResponse := { tx: Transaction }

11.4.8 Get Receipt

Ottieni una ricevuta di transazione con un ticket di transazione.

GetReceiptRequest := { hash: Ticket }

GetReceiptResponse := { rx: Receipt }

11.4.9 Get Block

Ottieni un contenuto di blocco. Facoltativamente permette di ottenere gli hash delle transazioni eseguite dal blocco specificato.

GetBlockRequest := { height: u64 // Block height (offset from the genesis block) txs: bool // Fetch transactions tickets as well }

GetBlockResponse := { block: Block txs: TransactionHashes }

TransactionsHashes : CHOICE { null, // Null if BlockRequest::txs is false SequenceOf Ticket // Sequence of block transaction tickets }

11.4.10 Get Account

Ottieni un contenuto dell'account.

GetAccountRequest := { id: String, // Account identifier data: SequenceOf string // Account data keys (may be empty) }

GetAccountResponse := { res: Account, data: SequenceOf DataResult }

DataResult : CHOICE { ByteBuffer, Null }

11.4.11 Exception

Qualcosa è andato storto durante l'elaborazione di un messaggio confermato. Questo messaggio contiene un messaggio di errore insieme all'origine.

Exception := { kind: string, source: string, }

11.4.12 Packed

Messaggio generalmente proveniente da una fonte esterna e inoltrato "così com'è" al servizio blockchain. Il messaggio compresso deve contenere ricorsivamente un messaggio serializzato in formato MessagePack. Il messaggio viene quindi deserializzato dal servizio blockchain prima di un'ulteriore elaborazione. Anche una risposta a un messaggio ricevuto come Packed viene inviata come Packed. Per motivi di sicurezza questo tipo di messaggio non può contenere un messaggio Stop.

Packed := ByteBuffer

11.5 Assets

Asset è la valuta che circola su una blockchain.

  • Un bene potrebbe essere:

    • Creato e aggiunto alla blockchain
    • Coniato, significa coniato dal nulla
    • Trasferito da un conto all'altro (il trasferimento potrebbe essere gestito da un contratto intelligente personalizzato (Smart-contracts/Basic-Asset-smart-contract.md), oppure creato appositamente per l'asset)
    • L'asset è memorizzato nel campo data dell'account service in un formato come questo:
     {
        "assets": {
     	  asset-account-id: {            // Asset account id
     		 "name": string,             // Asset name					 
     		 "creator": account-id,      // Caller account-id
     		 "url": integer,       		 // Web site of the asset
     		 "contract": bytes           // Hash of the contract that handle the asset
     	  },
        }
     }
    
  • Un account Asset contiene nella sua sezione dati tutte le caratteristiche del bene, sia statiche che dinamiche.

  • Il relativo contratto definisce il comportamento dell'asset.

  • Le funzionalità Asset sono specifiche per il tipo di asset e solo il relativo smart contract entra nel contenuto.

  • Gli asset possono avere elenchi di funzionalità completamente diversi (anche con nomi diversi per indicare la stessa cosa).

  • Un asset smart contract può essere utilizzato da più asset. Esempio:

    • Consideriamo due asset "semplici" come BTC e EUR, hanno lo stesso comportamento.
    • Quindi possono essere gestiti dallo stesso contratto intelligente basic_asset.
    • Ma hanno una configurazione diversa.

11.6 Synchronous Queries


11.6.1 Intro

Lo stato della blockchain può essere interrogato tramite il servizio GET REST API.

Il payload della risposta viene compresso utilizzando il formato "MessagePack" e inviato come byte semplici con l'intestazione Content-Type: application/octet-stream.

Attualmente il servizio consente di recuperare le seguenti informazioni:

  • ricevuta e contenuto della transazione.
  • informazioni sul blocco (intestazione).
  • informazioni sull'account/portafoglio.

11.6.2 Getting transaction content

Request URL: /api/v1/transaction/<ticket>

11.6.2.1 Input:

  • ticket: ticket di transazione come fornito dalla risposta del servizio di invio.

11.6.2.2 Output:

[
  [
    account,
    nonce,
    network,
    target,
    method,
    [
      signatureType,
      pubKeyValue
    ],
    args
  ],
  signature
]

In altre parole è la stessa struttura descritta [here] (Transaction-Format.md) ma senza chiavi.

NULL se ticket non trovato.

11.6.3 Getting transactions receipt

Request URL: /api/v1/receipt/<ticket>

11.6.3.1 Input:

  • ticket: ticket di transazione come fornito dalla risposta di invio.

11.6.3.2 Output:

[
  height
  index
  success
  returns
]
  • height: Numero. Numero di blocco in cui è stata inserita la transazione.
  • index: numero. Compensazione della transazione all'interno del blocco.
  • success: booleano. Vero se lo smart contract è stato eseguito correttamente.
  • returns: binario. Dati di output specifici del contratto intelligente.

NULL se ticket non trovato.

11.6.4 Getting Block info

Request URL: /api/v1/block/<height>

11.6.4.1 Input:

  • id: account identifier come descritto here.

11.6.4.2 Output:

[
  height,
  txs_count,
  prev_hash,
  txs_hash,
  rec_hash,
  state_hash,
]
  • height: Numero. Block offset all'interno della blockchain. Il blocco Genesis ha altezza 0.
  • txs_count: numero. Numero di transazioni all'interno di questo blocco.
  • prev_hash: Bytes. Hash del blocco precedente.
  • txs_hash: Bytes. Merkle tree root delle transazioni contenute all'interno di questo blocco.
  • rec_hash: Bytes. Merkle tree root delle ricevute contenute all'interno di questo blocco.
  • state_hash: Bytes. Merkle tree root dell'albero di tutti i conti (aka stato mondiale).

NULL se non trovato.

11.6.5 Getting account info

Request URL: /api/v1/account/<id>



11.6.5.1 Input:

  • id: account identifier come descritto here.

11.6.5.2 Output:

[
  id,
  assets,
  contract_ref,
  data_hash
]
  • id: String. Identificatore dell'account.
  • assets: mappa del nome dell'asset e dei suoi valori specifici dello smart contract (e.g. <"BTC", bytes>).
  • contract_ref: Bytes. Identificatore di contratto intelligente associato all'account. È definito come l'hash dei sorgenti WASM.
  • data_hash: Bytes. Merkle tree root dei dati associati all'account.ss

11.6.6 Session Example

11.6.7 Submit Transaction

  • type: POST
  • path: /api/vi/submit

Corpo di Richiesta:

{
  "data": {
    "account": "QmYHnEQLdf5...2SPgdXrJWFh5W696HPfq7i",
    "nonce": "a03a5500433cf88c",
    "network": "skynet",
    "target": "87b6239079719fc7e4349ec54baac9e04c20c48cf0c6a9d2b29b0ccf7c31c727",
    "method": "transfer",
    "caller": {
      "type": "ecdsa_p384r1",
      "value": "7cUWbhbYtrVqMpEyLXYh3RDAYgpNGzPFoA55ymm7NndERKxebZKMgXo35k3T4...w5k6aaYG96J4e2tWumVY4p1yv6hgSspSHVzvMKadYCHZByscm1oknaZjC86FF6"
    },
    "args": {
      "to": "QmTuhaS8rBRjBSxPYH...3fVtHJTuTbwwUSdnB8a",
      "amount": 19,
      "asset": "WPC"
    }
  },
  "signature": "MvbDchmXV1aHytKWr91aPCwsWAatmFG6fCusLmyJY6FcVf5ZZB4TjUhboXt...rAegZDH9rfBoHVTqihGscLnKbcLmGuoKWVu92uuX24MdK4ijKdiEx58E9QZpQyqS"
}

Corpo di risposta:

"12205b47bca14ab8cd339481a0717ac0b3f4b6601e8eb73804571b9335276306c791"

11.6.8 Get Transaction

  • type: GET
  • path: /api/v1/transaction/12205b47bca14ab8cd339481a0717ac0b3f4b6601e8eb73804571b9335276306c791

Corpo di risposta:

 
[
  [
    "QmYHn...",
    "a03a5500433cf88c",
    "skynet",
    "87b62390...",
    "transfer",
    [
      "ecdsa_p384r1",
      "7cUWbhbYtrV..."
    ],
    "82fcff2ba7..."
  ],
  "MvbDchmXV1..."
]

11.6.9 Get Receipt

  • type: GET
  • path: /api/v1/receipt/9QEDuUq12byR74Cf8W7DuUScz6S2fNpc69Kzrmf1ooQV

Corpo di risposta:

[
  344,
  0,
  true,
  null
]

11.6.10 Get Block

  • type: GET
  • path: /api/v1/block/344

Corpo di risposta:

[
  344,
  100,
  "e08ff0f6b4e0738c7b6fd1d033ba021cf1f36f882ff7167aae1e6a3bba10a8b5",
  "1c53e075e5962038dfeb5d2bae0581d4c1445345584168835f2935fdd4c7d880",
  "b2fc1d6be8bf1e55306ec56ab48bece541feec31187fe4438275c1cadaa4be1e",
  "34e3ecda323d9d8fd1b59c6e2026d694d5dd9eb821a57b9416dd3c1159778f16"
]

1!.6.11 Get Account

  • type: GET
  • path: /api/v1/account/QmYHnEQLdf5h7KYbjFPuHSRk2SPgdXrJWFh5W696HPfq7i {

Corpo di risposta:

[
  "QmYHnEQLdf5h7KYbjFPuHSRk2SPgdXrJWFh5W696HPfq7i",
  {
    "WPC": "94342fff0c"
  },
  "87b6239079719fc7e4349ec54baac9e04c20c48cf0c6a9d2b29b0ccf7c31c727",
  null,
]

12.1 Inizio


12.1.1 Installing Rust

  • Linux or Mac OS:
    $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
    • When shown choose the default settings
    • require git, curl and build-essential:
      # apt install git curl build-essential
      
  • Windows: see the rust official site

12.1.2 Download, compile and Run T.R.I.N.C.I. Node

  • The T.R.I.N.C.I. Node and Rust SDK source code can be found on github: Affidaty Blockchain

  • In order to build T.R.I.N.C.I. we need to install the following dependencies:

    clang libclang-dev protobuf-compiler
    
  • We can download the T.R.I.N.C.I. node repository and then build the node:

    $ git clone https://github.com/affidaty-blockchain/T.R.I.N.C.I.-node.git
    
  • Then we can build the executables.

    To download the needed Rust crates from crates.io

    $ cargo check
    

    To build the executables:

    $ cargo build --release
    

    To run the T.R.I.N.C.I. node:

    $ ./start
    

    This will execute the T.R.I.N.C.I. node using the config.toml configuration file.

12.1.3 Download T.R.I.N.C.I. Smart Contract Development Environment

$ git clone https://github.com/affidaty-blockchain/T.R.I.N.C.I.-smartcontracts.git
  • This crate depends on the T.R.I.N.C.I.-sdk crate.
  • The T.R.I.N.C.I. Rust SDK documentation can be found here.

12.1.3.1 Create a new contract

  • Use the script create_new_contract.sh in the directory /app-rs/:
    $ ./create_new_contract.sh
    
    then insert the new contract name. A project with the name provided will be created.
12.1.3.1.1 Launch the same cargo command for all the contracts:
$ ./cargo_broadcast.sh <COMMAND>

Example used to test all the contracts:

$ ./cargo_broadcast.sh test
12.1.3.1.2 Compile all the contracts with the rust installed on our computer
$ ./build_wasm.sh
  • Note: require rust with target wasm32-unknown-unknown
12.1.3.1.3 Compile all the contracts with a docker image
$ ./build_wasm_docker.sh
  • Note: requires docker installed on the system

12.1.3.2 registry directory

  • The registry directory contains the .wasm contracts

12.1.3.3 integration directory

  • The integration directory is a rust module that provide an environment for testing

12.1.3.4 Register a new smart contract

  • There are many ways to register a smart contract in T.R.I.N.C.I. Blockchain
    • Through a transaction to the Service account with arguments:

      args: {
          "name": string,          // contract name
          "version": string,       // contract version
          "description": string,   // contract description
          "url": string,           // contract web site
          "bin": binary,           // contract binary
      }
      
    • With the T.R.I.N.C.I. CLI:

      $ T.R.I.N.C.I.-cli 
            --host <T.R.I.N.C.I._host> \
            --port <T.R.I.N.C.I._port> \
            --path <T.R.I.N.C.I._path>/api/v1 \
            --network <T.R.I.N.C.I._network>
      
      • Enter in the cheats section:
      Enter 'help' to show available commands
      > cheats
      
      • Launch the register command:
      >>> register
      
      • Fill with the needed information:
        Service account: Qm...xyz                          # the Service account-id
        Service contract (optional multihash hex string):  # just press `enter`
        New contract name: My Cool Contract                # the contract name
        New contract version: 0.2.1                        # the contract version
        New contract description: This is my cool contract 
        New contract url: www.cool-contract.org
        New contract filename: <absolute_path>/my_cool_contract.wasm # contract file in our filesystem
      

12.1.4 Build a contract from scratch

  • In this section will are going to build a smart contract from zero

12.2.1 How to write a method callable from a transaction


A method to be executed through a transaction:

  • must have this signature:
    fn my_method(context: AppContext, args: SerializableStruct) -> WasmResult<Value>;
    • where SerializableStruct is a struct that derives the Serializable/Deserializable traits from the serde_derive crate.
    #[derive(Serialize, Deserialize, Debug)]
    #[cfg_attr(test, derive(PartialEq, Clone, Default))]
    struct SerializableStruct {
        pub field1: u32,
        pub field2: u8,
        ...
    }
  • must be exported by the app_export! sdk macro, like this:
    sdk::app_export!(..., my_method, ...);

12.2.2 Host Functions Wrapper

12.2.2.1 log

pub fn log(msg: &str);
  • send the message msg to the host to be logged.

12.2.2.2 load_data

pub fn load_data(key: &str) -> Vec<u8>;
  • load the serialized data stored at the given key from the current account.

12.2.2.3 store_data

pub fn store_data(key: &str, buf: &[u8]);
  • store the data passed as bytes array in the current account at the given key.

12.2.2.4 remove_data

pub fn remove_data(key: &str);
  • remove the data stored at the given key from the current account.

12.2.2.5 load_asset

pub fn load_asset(id: &str) -> Vec<u8>;
  • load asset from the account id specified.
  • the asset id is the current account id

12.2.2.6 store_asset

pub fn store_asset(id: &str, value: &[u8]);
  • store asset to the account id specified as byte array.
  • the asset id is the current account id

12.2.2.7 verify

pub fn verify(pk: &PublicKey, data: &[u8], sign: &[u8]) -> bool;
  • verify the signature of the given data by the given pk and algorithm

12.2.2.8 call

pub fn call(account: &str, method: &str, data: &[u8]) -> WasmResult<Vec<u8>>;
  • calls a method of an arbitrary smart contract passing the data as argument
  • if succeed returns the data from the method called

12.2.2.9 asset_balance

pub fn asset_balance(asset: &str) -> WasmResult<u64>;
  • get account balance for a given asset id.
  • this is an helper function over the lower level call(asset_id, "balance", args).

12.2.2.10 asset_transfer

pub fn asset_transfer(from: &str, to: &str, asset: &str, units: u64) -> WasmResult<()>;
  • transfer an amount of asset units to a destination account.
  • this is an helper function over the lower level call(asset_id, "transfer", args).

12.2.2.11 asset_lock

pub fn asset_lock(asset: &str, to: &str, value: LockType) -> WasmResult<()>;
  • Lock/Unlock the asset.
  • this is an helper function over the lower level call(asset_id, "lock", true/false).

12.2.2.12 load_asset_typed

pub fn load_asset_typed<T: DeserializeOwned + Default>(id: &str) -> T;
  • load asset with from the given account id and tries to convert it into a type.

12.2.2.13 store_asset_typed

pub fn store_asset_typed<T: Serialize>(id: &str, value: T);
  • store the typed asset to the given account id.

12.2.3 RAW Host Functions

The functions above are wrapper to the raw host_function that can be also called directly.

  • These functions require data structures to be written to memory and passed their address and size.
  • WasmSlice that is a i64 where is coded address and size of a memory location that stores the result.

12.2.3.1 hf_log

  • Allows to log strings
fn hf_log(address: i32, size: i32);

Example of usage:

...
let msg = String::from("Hello");
let buf = msg.as_bytes();
 
hf_log(buf.as_ref() as i32, buf.len() as i32);
 
...

12.2.3.2 hf_load_data

  • Load data from the account
fn hf_load_data(key_addr: i32, key_size: i32) -> WasmSlice;

12.2.3.3 hf_store_data

  • Store data to the account
fn hf_store_data(key_addr: i32, key_size: i32, data_addr: i32, data_size: i32);

12.2.3.4 hf_remove_data

  • Remove data from the account
fn hf_remove_data(key_addr: i32, key_size: i32);

12.2.3.5 hf_load_asset

  • load asset from the given account id
fn hf_load_asset(id_addr: i32, id_size: i32) -> WasmSlice;

12.2.3.6 hf_store_asset

  • store asset to the given account id
fn hf_store_asset(id_addr: i32, id_size: i32, value_addr: i32, value_size: i32);

12.2.3.7 hf_verify

  • verify the data signature
    fn hf_verify(
        pk_addr: i32,
        pk_size: i32,
        data_addr: i32,
        data_size: i32,
        sign_addr: i32,
        sign_size: i32,
    ) -> i32;

12.2.3.8 hf_call

  • call the method of another account
    fn hf_call(
        account_addr: i32,
        account_size: i32,
        method_addr: i32,
        method_size: i32,
        data_addr: i32,
        data_size: i32,
    ) -> WasmSlice;

12.2.4 Utility Functions

12.2.3.1 rmp_serialize_named

  • Serialize a type implementing Serialize trait using MessagePack format with named keys.
pub fn rmp_serialize_named<T>(val: &T) -> WasmResult<Vec<u8>>

12.2.4.2 rmp_serialize

  • Serialize a type implementing Serialize trait using MessagePack format.
pub fn rmp_serialize<T>(val: &T) -> WasmResult<Vec<u8>>

12.2.4.3 rmp_deserialize

  • Serialize a type implementing Deserialize trait using MessagePack format.
pub fn rmp_deserialize<'a, T>(buf: &'a [u8]) -> WasmResult<T>

12.2.4.4 PackedValue

  • Value that has been already packed, thus it doesn't require further processing and shall be taken "as-is".
pub struct PackedValue(pub Vec<u8>);

12.3.1 Write the pay-meal smart contract from scratch


Let create a contract that allows to split the meal bill between all the diners

  • The information that we need to initialize the contract is:

    • the restaurateur account
    • the list of customers
    • the part for each customer
    • the asset for the payment
  • Once the contract is initialized a customer must apply to pay is share of the bill.

  • Once all the customers have paid their share the restaurateur could close the contract, and collect the asset.

  • Note: We use a TAI compliant asset

    • To improve this contract we could use an Advanced Asset and implement the after_transfer method to automagically initialize the contract after a transfer of a certain amount of asset in this account.
  • Note: The following code is used as example, the full and properly working code can be found in the repository.

  • init, get_info, apply, close will become contract methods.

12.3.1.1 init method

  • The init method in a smart contract usually should do some checks on the data (if needed), then store it in the config field of the account.
  • In this example can be called only by the account owner.
    • Note: This prevent the use of Non-Fungible Account (like "#MYACCOUNT")
12.3.1.1.1 Writing and testing the init arguments
  • In the project we have just create open the file types.rs and add a structure for the init args:

    // Init Args
    #[derive(Serialize, Deserialize)]
    #[cfg_attr(test, derive(Debug, PartialEq, Clone))]
    pub struct InitArgs<'a> {
        pub restaurateur: &'a str, // is the merchant account
        pub asset: &'a str,        // is the asset account
        pub part: u64,             // is the the share for each diner
        pub customers: BTreeMap<&'a str, bool>, // the diners list
    }
  • Every contract method expects a binary argument that is message pack data.

  • Now we create a proper function in the tests section for the serialization/deserialization test of the init arguments.

    • create some account const field, like this:

      pub(crate) const RESTAURATEUR_ID: &str = "QmRestaurateurT8ijW7REd3KqN1kGBgYxFWsxajjguLky";
      pub(crate) const ASSET_ID: &str = "QmAssetT8ijsdfWsd7REf35d3KqN1kGBgYxFWsxajjguLk";
      pub(crate) const CUSTOMER1_ID: &str = "QmCustomer1-T8ijsdfWs35d3KqN1kGBgYxFWsxajjguLk";
      pub(crate) const CUSTOMER2_ID: &str = "QmCustomer2-T8ijsdfWs35d3KqN1kGBgYxFWsxajjguLk";
      pub(crate) const CUSTOMER3_ID: &str = "QmCustomer3-T8ijsdfWs35d3KqN1kGBgYxFWsxajjguLk";
    • create a function to create a InitArgs filled struct (will be useful for the method tests):

      pub(crate) fn create_init_args() -> InitArgs<'static> {
         let mut customers = BTreeMap::new();
         customers.insert(CUSTOMER1_ID, false);
         customers.insert(CUSTOMER2_ID, false);
         customers.insert(CUSTOMER3_ID, false);
         InitArgs {
             restaurateur: RESTAURATEUR_ID,
             asset: ASSET_ID,
             part: 30,
             customers,
         }
      }
    • add an empty constant that represent the hex serialized value of the init arguments, like this:

      const INIT_ARGS_HEX: &str = "";
    • write the tests for the serialization/deserialization:

      #[test]
      fn init_args_serialize() {
          let args = create_init_args();
      
          let buf = T.R.I.N.C.I._sdk::rmp_serialize(&args).unwrap();
      
          assert_eq!(hex::encode(&buf), INIT_ARGS_HEX);
      }
      
      #[test]
      fn init_args_deserialize() {
          let expected = create_init_args();
      
          let buf = hex::decode(INIT_ARGS_HEX).unwrap();
      
          let args: InitArgs = T.R.I.N.C.I._sdk::rmp_deserialize(&buf).unwrap();
      
          assert_eq!(args, expected);
      }
      • launch the test init_args_serialize, this obviously fails, but we can see how is the expected hex, we can try to deserialize it with ()[online tools] and replace in the INIT_ARGS_HEX constant.
        const INIT_ARGS_HEX: &str = "94d92e516d5265737461757261746575725438696a5737524564334b714e316b474267597846577378616a6a67754c6b79d92e516d41737365745438696a73646657736437524566333564334b714e316b474267597846577378616a6a67754c6b1e83d92e516d437573746f6d6572312d5438696a7364665773333564334b714e316b474267597846577378616a6a67754c6bc2d92e516d437573746f6d6572322d5438696a7364665773333564334b714e316b474267597846577378616a6a67754c6bc2d92e516d437573746f6d6572332d5438696a7364665773333564334b714e316b474267597846577378616a6a67754c6bc2";
      • launch all the tests.
12.3.1.1.2 Writing and testing the init method
  • Open the file lib.rs
  • In T.R.I.N.C.I. rust contract a method has the following signature:
    fn function_name(ctx: AppContext, args: ArgumentsType) -> WasmResult<ReturnType>;
    where ArgumentsType and ReturnType are serializable structs.
  • In our case the init method shall take a InitArgs arguments type (we have just defined it in types.rs), and will return nothing or an Error with a WasmResult type that wraps a std::result::Result type, for now we write this:
    /// Init method
    fn init(_ctx: AppContext, _args: InitArgs) -> WasmResult<()> {
        Ok(())
    }
    • The rust compiler warning us that the init method is not used, this because we have not told the sdk to export this method. To do this we look for a row like this:
    T.R.I.N.C.I._sdk::app_export!(...);
    This is the macro that allows to make available our methods to the world, and simply add the init method inside the parenthesis, like this:
    T.R.I.N.C.I._sdk::app_export!(init);
  • Now the warning is disappeared but the init method still do nothing, to keep the contract simple we could implement the init method like this:
    /// Init method
    fn init(_ctx: AppContext, args: InitArgs) -> WasmResult<()> {
        T.R.I.N.C.I._sdk::store_account_data_mp!("config", &args)
    }
  • If we improve our contract we could add a check on the caller, and allow the contract initialization only at the account owner, putting the following at the start of the method code:
    if ctx.owner != ctx.caller {
        return Err(WasmError::new("not authorized"));
    }
  • To prevent not authorized asset withdraw we must use the TAI asset lock, like this:
    ...
    // Withdraw lock for the asset under escrow.
    T.R.I.N.C.I._sdk::asset_lock(args.asset, ctx.owner, T.R.I.N.C.I._sdk::tai::LockType::Withdraw)?;
    ...
  • Now we wrote a simple test function for the init method:
    #[test]
    fn test_init() {
        // we use an sdk function to create a context for the contract test
        let ctx = not_wasm::create_app_context(PAY_ID, PAY_ID);     
    
        // we use the function written previously to create the init arguments
        let args = create_init_args();
    
        // Associate a mock lock to the asset account
        not_wasm::set_contract_method(ASSET_ID, "lock", not_wasm::asset_lock);
    
        // This function simulate the contract method execution
        not_wasm::call_wrap(init, ctx, args.clone()).unwrap();
    
        // We make some checks on the account data to see
        // if the configuration as been properly written
        let buf = not_wasm::get_account_data(PAY_ID, "config");
        let data: InitArgs = rmp_deserialize(&buf).unwrap();
    
        assert_eq!(data, args);
    }
  • If we have added a owner checks we could write a test to check if the method fails if we call it from another account:
    #[test]
    fn test_init_not_authorized() {
        let ctx = not_wasm::create_app_context(PAY_ID, "Unknown");
        let args = create_init_args();
    
        // Associate a mock lock to the asset account
        not_wasm::set_contract_method(ASSET_ID, "lock", not_wasm::asset_lock);
    
        let err = not_wasm::call_wrap(init, ctx, args.clone()).unwrap_err();
    
        // Checks on the error
        assert_eq!(err.to_string(), "not authorized");
    }
  • To exercise we could write a more sophisticated init that take the total amount and calculate the customer part (the eventually round up could be see as the tip :) ) and store a struct different from the init args.

12.3.1.2 get_info method

  • The get_info method allows to retrieve the information (config) of the contract
  • Can be called only by the account involved in the contract (the restaurateur or a customer)

12.3.1.2.1 get_info arguments

  • In this case the get_info argument are null:
    args: {}
    
  • We can use an SDK struct to represent a null arguments, PackedValue.
12.3.1.2.2 get_info returns
  • The result is the config struct as serialized struct with names.
  • We realize that a status field would have been useful and then we go to insert it in the InitArgs struct, making all the necessary adjustments.
    {
       "restaurateur": account-id, // is the merchant account
       "asset": account-id,        // is the asset account
       "part": 123,                // is the the share for each diner
       "customers": {              // the diners list and the payment status
           "customer_1": true,
           "customer_2": false,
           "customer_3": false,
       }, 
       status: "open",             // contract status "open" or "closed"
    }
12.3.1.2.2 Writing and testing the get_info method
  • This could be an example of the implementation of the get_info method:
 /// Get_Info method
fn get_info(ctx: AppContext, _args: PackedValue) -> WasmResult<PackedValue> {
    // Load the contract configuration
    let buf = T.R.I.N.C.I._sdk::load_data("config");
    let config: InitArgs = match rmp_deserialize(&buf) {
        Ok(val) => val,
        Err(_) => return Err(WasmError::new("not initialized")),
    };

    // Checks on the authorization
    let mut auth_list = vec![config.restaurateur];
    config
        .customers
        .iter()
        .for_each(|(&customer, _)| auth_list.push(customer));

    match auth_list.iter().find(|&&elem| elem == ctx.caller) {
       Some(_) => {
           let buf = rmp_serialize_named(&config)?;
           Ok(PackedValue(buf))
       }
       None => Err(WasmError::new("not authorized")),
   }
}
  • Let's write a test function for the get_info method:
#[test]
fn test_get_info() {
   // Prepare the environment
   // Prepare the context
   let ctx = not_wasm::create_app_context(PAY_ID, CUSTOMER1_ID);
 
   // Prepare the account data/config
   let data = create_init_args();
   let data = rmp_serialize(&data).unwrap();
   not_wasm::set_account_data(PAY_ID, "config", &data);
 
   let args = PackedValue::default();
 
   let res = not_wasm::call_wrap(get_info, ctx, args).unwrap();
 
   let data: Value = rmp_deserialize(&res.0).unwrap();
 
   // Checks on the contract info
   let restaurateur = data.get(&value!("restaurateur")).unwrap().as_str().unwrap();
 
   assert_eq!(restaurateur, RESTAURATEUR_ID);
}
  • To exercise we could test the get_info with an not initialized contract and the apply from a unknown account

12.3.1.3 apply method

The apply method performs the payment from a customer to the contract account for his bill share.

12.3.1.3.1 apply arguments
  • In this case the apply argument are null:
    args: {}
    
12.3.1.3.2 Writing and testing the apply method
  • The apply method could be like this:

    /// Apply method
    fn apply(ctx: AppContext, _args: PackedValue) -> WasmResult<()> {
        // Load the contract configuration
        let buf = T.R.I.N.C.I._sdk::load_data("config");
        let mut config: InitArgs = match rmp_deserialize(&buf) {
            Ok(val) => val,
            Err(_) => return Err(WasmError::new("not initialized")),
        };
    
        // Check if the caller is in the list and have already paid
        if let Some(val) = config.customers.get_mut(ctx.caller) {
            if !*val {
                // Make the payment
                T.R.I.N.C.I._sdk::asset_transfer(ctx.caller, ctx.owner, config.asset, config.part)
                    .map_err(|_| WasmError::new("transfer from caller failed"))?;
                *val = true;
            }
        } else {
            return Err(WasmError::new("not authorized"));
        };
    
        // Store the config and exit
        T.R.I.N.C.I._sdk::store_account_data_mp!("config", &config)?;
    
        Ok(())
    }
  • In this method will load the contract config and check if the caller is in the customers field and if has already paid his part

    • If the caller has not already paid a transfer will be performed from the caller to the contract (this could require a previously request for a delegation from the caller in the Asset account)
  • Now we are going to write some tests for the apply method:

    #[test]
    fn test_apply() {
        // Prepare the environment
        // Prepare the context
        let ctx = not_wasm::create_app_context(PAY_ID, CUSTOMER1_ID); 
    
        // Prepare the account data/config
        let data = create_init_args();
        let data = rmp_serialize(&data).unwrap();
        not_wasm::set_account_data(PAY_ID, "config", &data); 
    
        // Give the customer some asset
        not_wasm::set_account_asset_gen(CUSTOMER1_ID, ASSET_ID, Asset::new(100)); 
    
        // Associate a mock transfer to the asset account
        not_wasm::set_contract_method(ASSET_ID, "transfer", not_wasm::asset_transfer); 
        let args = PackedValue::default(); 
        
        not_wasm::call_wrap(apply, ctx, args).unwrap(); 
    
        // Checks on the contract account config
        let buf = not_wasm::get_account_data(PAY_ID, "config");
        let data: InitArgs = rmp_deserialize(&buf).unwrap();
        let customer1 = data.customers.get(CUSTOMER1_ID).unwrap(); 
    
        assert!(customer1); 
    
        // Checks on the contract asset
        let asset: Asset = not_wasm::get_account_asset_gen(PAY_ID, ASSET_ID); 
    
        assert_eq!(asset.units, 30);
    }
    • The not_wasm_ module contains some useful functions that allow a user to build an environment to test the contract methods and performs some checks on the results:
      • not_wasm::create_app_context(owner, caller) -> AppContext - builds a context struct to pass to the methods that specifies the account owner and the account that call the method.
      • not_wasm::set_account_data(account_id, key, data) - allows to initialize an account data field with some content (binary), stored at key.
      • not_wasm::get_account_data(account_id, key) - allows to retrieve some data (as binary) from an account data field.
      • not_wasm::set_account_asset_gen(account_id, asset_id, asset) - allows to put some asset (must follow the TAI) in the asset_id field of the account account_id.
      • not_wasm::get_account_asset_gen(account_id, asset_id) - allows to retrieve the asset from the account specified.
      • not_wasm::set_contract_method(account_id, method_name, method_func) - allows to associate a mock function to the call of a method of an account contract in order to simulate a certain behaviour.
  • To exercise we could test the apply with an not initialized contract and the apply from a unknown account

12.3.1.4 close method

  • The close method allows the restaurateur to collect the asset from the contract
  • Can be called only by the restaurateur account
  • If every customer has paid the contract status will be set to closed, otherwise will be performed only the transfer of the current amount and the status will be leave "open".
12.3.1.4.1 close arguments
  • In this case the close argument are null:
    args: {}
    
12.3.1.4.2 Writing and testing the close method
  • The close method looks like this:
/// Close method
fn close(ctx: AppContext, _args: PackedValue) -> WasmResult<()> {
    // Load the contract configuration
    let buf = T.R.I.N.C.I._sdk::load_data("config");
    let mut config: InitArgs = match rmp_deserialize(&buf) {
        Ok(val) => val,
        Err(_) => return Err(WasmError::new("not initialized")),
    };

    // Check if the caller is the restaurateur
    if ctx.caller != config.restaurateur {
        return Err(WasmError::new("not authorized"));
    }

    // Check if the contract is still opened
    if config.status != "open" {
        return Err(WasmError::new("contract closed"));
    }

    // Unlock the asset
    T.R.I.N.C.I._sdk::asset_lock(config.asset, ctx.owner, T.R.I.N.C.I._sdk::tai::LockType::None)?;

    // Get Balance
    let amount: u64 = T.R.I.N.C.I._sdk::asset_balance(config.asset)?;

    // Perform the Transfer
    T.R.I.N.C.I._sdk::asset_transfer(ctx.owner, config.restaurateur, config.asset, amount)?;

    // Lock again the asset
    T.R.I.N.C.I._sdk::asset_lock(config.asset, ctx.owner, T.R.I.N.C.I._sdk::tai::LockType::Withdraw)?;

    // If all the customers have paid set the status to close
    if !config.customers.values().any(|&val| !val) {
        //  All the customers have paid
        config.status = "close";
        T.R.I.N.C.I._sdk::store_account_data_mp!("config", &config)?;
    }

    Ok(())
}
  • Pay attention to the asset lock handling!

12.3.2 Compiling the contract

  • To compile the contract we go in the '/app-rs' directory and: if we want to build the contract with our rust toolchain we launch the command:

    $ ./build_wasm.sh
    

    or if we want to build the contract with a toolchain in a pre-build docker image:

    $ ./build_wasm_docker.sh
    

    or we can manually compile from the contract directory with the command:

    $ cargo build --release --target wasm32-unknown-unknown
    

    then optimize the compiled file and put the result in the registry:

    $ wasm-opt ./target/wasm32-unknown-unknown/release/<contract_name>.wasm -o ../../registry/<contract_name>.wasm --strip
    
  • The previously commands will build each contract in the directory and copy the .wasm files in the <repo>/registry directory

12.3.3 Integration Test

  • Now that we have made a contract by scratch and tested its methods we need to perform a more accurate test using the real contract that we have mocked in the unit tests (in this case just the asset contract)

12.3.3.1 The Environment

  • The integration test project is inside the T.R.I.N.C.I. project, in our repository we could find a project under <repo>/integration that uses the T.R.I.N.C.I. modules to perform integration test.
  • We need to create a new pay_meal.rs file (we could created it from scratch or we could just copy and modify another contract file)
  • The core of an integration test is the test method itself:
    #[test]
    fn pay_meal_test() {
        // Instance the application.
        let mut app = TestApp::default();
    
        // Create and execute transactions.
        let txs = create_txs();
        let rxs = app.exec_txs(txs);
        check_rxs(rxs);
    
        // Performs account checks
        ...
    }
    • In the first section we initialize the environment
    • Then we use a function to create the transactions to execute
    • Then we execute the transactions
    • Then we check the answer
    • Then we perform other checks on the account

12.3.3.2 Build the Various Scenarios

  • When we build an integration test we need to think it like a scenario where our contract is the main actor. In our case we could think something like this:
    • We have 3 people (Luigi, Bruno, Marco) that had dinner at Mario's Pizza
    • They have spent 90 units of asset in total (30 each)
    • Marco get the bill information
    • Luigi pays his bill
    • Luigi tries to pay again his bill. This shall fail
    • Piero (not an actual customer) tries to pay in this contract. This shall fail.
    • Piero get the contract information. This shall fail.
    • Marco try to close the contract. This shall fail.
    • Mario (the restaurateur) try to close the contract.
    • Marco and Bruno pay their bill.
    • Mario (the restaurateur) try to close the contract.
    • Mario get the contract information.

12.3.3.3 Build the Transactions creator

  • Lets build the transaction for the previously scenario.
  • We use a function like this (see the full code):
fn create_txs() -> Vec<Transaction> {
    let contract_info = ACCOUNTS_INFO.get(PAY_ALIAS).unwrap();
    let restaurateur_info = ACCOUNTS_INFO.get(RESTAURATEUR_ALIAS).unwrap();
    let marco_info = ACCOUNTS_INFO.get(MARCO_ALIAS).unwrap();
    let luigi_info = ACCOUNTS_INFO.get(LUIGI_ALIAS).unwrap();
    let bruno_info = ACCOUNTS_INFO.get(BRUNO_ALIAS).unwrap();
    let piero_info = ACCOUNTS_INFO.get(PIERO_ALIAS).unwrap();
    let asset_info = ACCOUNTS_INFO.get(ASSET_ALIAS).unwrap();

    vec![
        // 0. Initialize src asset
        asset_init_tx(asset_info, ASSET_ALIAS),
        // 1. Mint some units in customers account.
        asset_mint_tx(asset_info, marco_info, 100),
        // 2. Mint some units in customers account.
        asset_mint_tx(asset_info, luigi_info, 100),
        // 3. Mint some units in customers account.
        asset_mint_tx(asset_info, bruno_info, 100),
        // 4. Mint some units in customers account.
        asset_mint_tx(asset_info, piero_info, 100),
        // 5. Initialize contract account.
        contract_init_tx(
            contract_info,
            restaurateur_info,
            asset_info,
            marco_info,
            luigi_info,
            bruno_info,
            30,
        ),
        // 6. Marco get the contract info
        contract_get_info_tx(contract_info, marco_info),
        // 7. Luigi add delegation to pay the bill
        asset_add_delegation_tx(asset_info, luigi_info, contract_info, 30),
        // 8. Luigi pays his bill
        contract_apply_tx(contract_info, luigi_info),
        // 9. Piero tries to pay. This shall fail.
        contract_apply_tx(contract_info, piero_info),
        // 10. Piero tries to get contract information. This shall fail.
        contract_get_info_tx(contract_info, piero_info),
        // 11. Marco tries to close the contract. This shall fail.
        contract_close_tx(contract_info, marco_info),
        // 12. Mario (the restaurateur) tries to close the contract.
        contract_close_tx(contract_info, restaurateur_info),
        // 13. Bruno add delegation to pay the bill
        asset_add_delegation_tx(asset_info, luigi_info, contract_info, 30),
        // 14. Bruno pays his bill
        contract_apply_tx(contract_info, luigi_info),
        // 15. Marco add delegation to pay the bill
        asset_add_delegation_tx(asset_info, marco_info, contract_info, 30),
        // 16. Marco pays his bill
        contract_apply_tx(contract_info, marco_info),
        // 17. Mario (the restaurateur) tries to close the contract.
        contract_close_tx(contract_info, restaurateur_info),
        // 18. Mario get the contract information
        contract_get_info_tx(contract_info, restaurateur_info),
    ]
}
  • There are some function that are relative at other contract that are relate to the contracts we are going to interact with (in this case just the asset with init and mint)

12.3.3.4 Build the Check Receipts

  • The method that checks the receipts will check if the transaction has given the expected result (null, or some data) or an error (in this case we check the expected error code):

    fn check_rxs(rxs: Vec<Receipt>) {
        // 0. Initialize src asset
        assert!(rxs[0].success);
        // 1. Mint some units in customers account.
        assert!(rxs[1].success);
        // 2. Mint some units in customers account.
        assert!(rxs[2].success);
        // 3. Mint some units in customers account.
        assert!(rxs[3].success);
        // 4. Mint some units in customers account.
        assert!(rxs[4].success);
        // 5. Initialize contract account.
        assert!(rxs[5].success);
        // 6. Marco get the contract info
        assert!(rxs[6].success);
        // Checks on the config
        let config: Value = rmp_deserialize(&rxs[6].returns).unwrap();
        let status = config.get(&value!("status")).unwrap().as_str().unwrap();
        assert_eq!(status, "open");
        // 7. Luigi add delegation to pay the bill
        assert!(rxs[7].success);
        // 8. Luigi pays his bill
        assert!(rxs[8].success);
        // 9. Piero tries to pay. This shall fail.
        assert!(!rxs[9].success);
        assert_eq!(
            String::from_utf8_lossy(&rxs[9].returns),
            "smart contract fault: not authorized"
        );
        // 10. Piero tries to get contract information. This shall fail.
        assert!(!rxs[10].success);
        assert_eq!(
            String::from_utf8_lossy(&rxs[9].returns),
            "smart contract fault: not authorized"
        );
        // 11. Marco tries to close the contract. This shall fail.
        assert!(!rxs[11].success);
        assert_eq!(
            String::from_utf8_lossy(&rxs[9].returns),
            "smart contract fault: not authorized"
        );
        // 12. Mario (the restaurateur) tries to close the contract.
        assert!(rxs[12].success);
        // 13. Bruno add delegation to pay the bill
        assert!(rxs[13].success);
        // 14. Bruno pays his bill
        assert!(rxs[14].success);
        // 15. Marco add delegation to pay the bill
        assert!(rxs[15].success);
        // 16. Marco pays his bill
        assert!(rxs[16].success);
        // 17. Mario (the restaurateur) tries to close the contract.
        assert!(rxs[17].success);
        // 18. Mario get the contract information
        assert!(rxs[18].success);
        // Checks on the config
        let config: Value = rmp_deserialize(&rxs[18].returns).unwrap();
        let status = config.get(&value!("status")).unwrap().as_str().unwrap();
        assert_eq!(status, "close");
    }
  • Note: Pay attention adding transaction in the middle of the above create_txs method, because this implies that the receipts index must be update in each following assert!

  • Last thing we add some blockchain checks:

    ...
    // Blockchain check.
    let asset_info = ACCOUNTS_INFO.get(ASSET_ALIAS).unwrap();
    let contract_info = ACCOUNTS_INFO.get(PAY_ALIAS).unwrap();
    let restaurateur_info = ACCOUNTS_INFO.get(RESTAURATEUR_ALIAS).unwrap();
    let marco_info = ACCOUNTS_INFO.get(MARCO_ALIAS).unwrap();
    let luigi_info = ACCOUNTS_INFO.get(LUIGI_ALIAS).unwrap();
    let bruno_info = ACCOUNTS_INFO.get(BRUNO_ALIAS).unwrap();
    let piero_info = ACCOUNTS_INFO.get(PIERO_ALIAS).unwrap();
    
    let contract_account = app.account(&contract_info.id).unwrap();
    let contract_asset: Asset =
        serialize::rmp_deserialize(&contract_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(contract_asset.units, 0);
    
    let restaurateur_account = app.account(&restaurateur_info.id).unwrap();
    let restaurateur_asset: Asset =
        serialize::rmp_deserialize(&restaurateur_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(restaurateur_asset.units, 90);
    
    let bruno_account = app.account(&bruno_info.id).unwrap();
    let bruno_asset: Asset =
        serialize::rmp_deserialize(&bruno_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(bruno_asset.units, 70);
    
    let marco_account = app.account(&marco_info.id).unwrap();
    let marco_asset: Asset =
        serialize::rmp_deserialize(&marco_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(marco_asset.units, 70);
    
    let luigi_account = app.account(&luigi_info.id).unwrap();
    let luigi_asset: Asset =
        serialize::rmp_deserialize(&luigi_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(luigi_asset.units, 70);
    
    let piero_account = app.account(&piero_info.id).unwrap();
    let piero_asset: Asset =
        serialize::rmp_deserialize(&piero_account.load_asset(&asset_info.id)).unwrap();
    assert_eq!(piero_asset.units, 100);
    ...