FlowCards: Un Framework Dichiarativo per lo Sviluppo di dApp Ergo
29 aprile 2020

Con ringraziamenti a Robert Kornacki per la revisione della bozza.
Introduzione
ErgoScript è il linguaggio dei contratti intelligenti utilizzato
dalla blockchain Ergo. Sebbene abbia una sintassi concisa adottata da Scala/Kotlin, può sembrare
confuso all'inizio perché concettualmente ErgoScript è piuttosto diverso rispetto ai
linguaggi convenzionali che tutti conosciamo e amiamo. Questo perché Ergo è una blockchain basata su UTXO,
mentre i contratti intelligenti sono tradizionalmente associati a sistemi basati su account
come Ethereum. Tuttavia, il modello di transazione di Ergo ha molti vantaggi rispetto al modello
basato su account e con il giusto approccio può essere persino significativamente più facile sviluppare contratti Ergo
rispetto a scrivere e fare debug del codice Solidity.
Di seguito tratteremo gli aspetti chiave del modello di contratto Ergo che lo rendono diverso:
Paradigma
Il modello di account di Ethereum è imperativo. Ciò significa che il compito tipico di inviare monete da
Alice a Bob richiede di modificare i saldi nello storage come una serie di operazioni. Il modello di programmazione basato su UTXO di Ergo,
però, è dichiarativo. I contratti ErgoScript specificano le condizioni affinché
una transazione venga accettata dalla blockchain (non modifiche da apportare allo stato di storage
come risultato dell'esecuzione del contratto).
Scalabilità
Nel modello di account di Ethereum sia le modifiche allo storage che i controlli di validità vengono eseguiti
su catena durante l'esecuzione del codice. Al contrario, le transazioni Ergo vengono create
fuori catena e solo i controlli di validazione vengono eseguiti su catena, riducendo così la quantità di
operazioni eseguite da ogni nodo sulla rete. Inoltre, a causa dell'immutabilità del
grafico delle transazioni, sono possibili varie strategie di ottimizzazione per migliorare il throughput
delle transazioni al secondo nella rete. Sono anche possibili nodi di verifica leggeri, facilitando ulteriormente la scalabilità e l'accessibilità della rete.
Stato condiviso
Il modello basato su account si basa su uno stato mutabile condiviso, noto per portare
a semantiche complesse (e sottili bug da milioni di dollari) nel contesto del calcolo concorrente/
distribuito. Il modello di Ergo si basa su un grafo immutabile di transazioni. Questo
approccio, ereditato da Bitcoin, si adatta bene alla natura concorrente e distribuita delle
blockchain e facilita i client leggeri senza fiducia.
Potere espressivo
Ethereum ha sostenuto l'esecuzione di un linguaggio Turing completo sulla blockchain. Ha
theoreticamente promesso un potenziale illimitato, tuttavia nella pratica sono emerse gravi
limitazioni a causa dell'eccessivo ingombro della blockchain, bug sottili da milioni di dollari, costi del gas che
limitano la complessità dei contratti e altri problemi simili. D'altra parte, Ergo estende UTXO per abilitare
la Turing-completezza limitando la complessità del linguaggio ErgoScript stesso. Lo stesso
potere espressivo viene raggiunto in un modo diverso e più semanticamente solido.
Con tutti i punti sopra, dovrebbe essere chiaro che ci sono molti vantaggi nel modello utilizzato da Ergo.
Nel resto di questo articolo ti presenterò il concetto di FlowCards - un componente per sviluppatori di dApp
che consente di progettare contratti Ergo complessi in modo dichiarativo e visivo.
Da Imperativo a Dichiarativo
Nel modello di programmazione imperativa di Ethereum, una transazione è una sequenza di operazioni
eseguite dalla VM di Ethereum. La seguente funzione Solidity
implementa un trasferimento di token da sender a receiver. La transazione inizia quando
sender chiama questa funzione su un'istanza di un contratto e termina quando la funzione
restituisce.
// Invia un importo di monete esistenti da qualsiasi chiamante a un indirizzo
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Saldo insufficiente.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
La funzione controlla prima le pre-condizioni, poi aggiorna lo storage (cioè i saldi) e
infine pubblica la post-condizione come evento Sent. Il gas consumato dalla
transazione viene inviato al miner come ricompensa per l'esecuzione di questa transazione.
A differenza di Ethereum, una transazione in Ergo è una struttura dati che contiene un elenco di monete di input
che spende e un elenco di monete di output che crea, preservando i saldi totali di
ERG e token (in cui Ergo è simile a Bitcoin).
Tornando all'esempio sopra, poiché Ergo supporta nativamente i token, per questo
specifico esempio di invio di token non è necessario scrivere alcun codice in ErgoScript. Invece,
è necessario creare la transazione 'send' mostrata nella figura seguente, che descrive
lo stesso trasferimento di token ma in modo dichiarativo.

L'immagine descrive visivamente i seguenti passaggi, che l'utente della rete deve
eseguire:
- Selezionare le scatole non spese del mittente, contenenti in totale
tB >= amountdi token eB >= txFee + minErgERG. - Creare una scatola di output
targetprotetta dalla chiave pubblica delreceiverconminErg
ERG eamountdi tokenT. - Creare un output fee protetto dal contratto
minerFeecontxFeeERG. - Creare un output change protetto dalla chiave pubblica del
sender, contenente
B - minErg - txFeeERG etB - amountdi tokenT. - Creare una nuova transazione, firmarla utilizzando la chiave segreta del mittente e inviarla alla rete Ergo.
Ciò che è importante comprendere qui è che tutti questi passaggi vengono eseguiti fuori catena (ad esempio utilizzando l'API delle transazioni di Appkit) dall'applicazione
dell'utente. I nodi della rete Ergo non devono ripetere questo processo di creazione della transazione,
devono solo convalidare la transazione già formata. I contratti ErgoScript sono memorizzati negli
input della transazione e controllano le condizioni di spesa. Il nodo esegue i
contratti su catena quando la transazione viene convalidata. La transazione è valida se tutte
le condizioni sono soddisfatte.
Quindi, in Ethereum quando "inviamo un importo da mittente a destinatario" stiamo letteralmente
modificando i saldi e aggiornando lo storage con un insieme concreto di comandi. Questo avviene
su catena e quindi una nuova transazione viene anche creata su catena come risultato di questo processo.
In Ergo (come in Bitcoin) le transazioni vengono create fuori catena e i nodi della rete
verificano solo. Gli effetti della transazione sullo stato della blockchain sono che le monete di input
(o Box nel gergo di Ergo) vengono rimosse e le scatole di output vengono aggiunte al
UTXO set.
Nell'esempio sopra non utilizziamo un contratto ErgoScript ma assumiamo invece che venga
utilizzato un controllo di firma come pre-condizione di spesa. Tuttavia, in scenari di applicazione più complessi, dobbiamo ovviamente utilizzare ErgoScript, di cui parleremo nel prossimo capitolo.
Da Cambiare Stato a Controllare Contesto
Nell'esempio della funzione send abbiamo prima controllato la pre-condizione (require(amount <= balances[msg.sender],...)) e poi cambiato lo stato (cioè aggiornato i saldi
balances[msg.sender] -= amount). Questo è tipico nelle transazioni di Ethereum. Prima
che possiamo cambiare qualcosa, dobbiamo controllare se è valido farlo.
In Ergo, come abbiamo discusso in precedenza, lo stato (cioè il set di box UTXO) viene cambiato implicitamente quando una
transazione valida è inclusa in un blocco. Pertanto, dobbiamo solo controllare le pre-condizioni prima che
la transazione possa essere aggiunta al blocco. Questo è ciò che fanno i contratti ErgoScript.
Non è possibile "cambiare lo stato" in ErgoScript perché è un linguaggio per controllare
le pre-condizioni per la spesa delle monete. ErgoScript è un linguaggio puramente funzionale senza effetti collaterali che opera su valori di dati immutabili. Ciò significa che tutti gli input, output e
altri parametri di transazione disponibili in uno script sono immutabili. Questo, tra le altre
cose, rende ErgoScript un linguaggio molto semplice che è facile da imparare e sicuro da usare. Simile a
Bitcoin, ogni box di input contiene uno script, che deve restituire il valore true per
- consentire la spesa della box (cioè rimuoverla dal set UTXO) e 2) aggiungere la
transazione al blocco.
Se vogliamo essere pignoli, è quindi errato (parlando rigorosamente) pensare a ErgoScript come al linguaggio dei
contratti Ergo, perché è il linguaggio delle proposizioni (predicati logici, formule,
etc.) che proteggono le box da spese "illegali". A differenza di Bitcoin, in Ergo l'intera
transazione e una parte del contesto attuale della blockchain sono disponibili per ogni script. Pertanto,
ogni script può controllare quali output sono creati dalla transazione, i loro importi di ERG e token
(utilizzeremo questa capacità nei nostri contratti DEX di esempio), il numero del blocco corrente
ecc.
In ErgoScript definisci le condizioni di se le modifiche (cioè la spesa delle monete) sono consentite
per avvenire in un dato contesto. Questo è in contrasto con la programmazione delle modifiche
in modo imperativo nel codice di un contratto.
Mentre il modello di transazione di Ergo sblocca una gamma intera di applicazioni come (DEX, DeFi
Apps, LETS, ecc.), progettare contratti come pre-condizioni per la spesa delle monete (o script di protezione)
non è intuitivo. Nelle prossime sezioni considereremo una notazione grafica utile
per progettare contratti in modo dichiarativo utilizzando FlowCard Diagrams, che è una rappresentazione visiva
dei componenti eseguibili (FlowCards).
I FlowCards mirano a semplificare radicalmente lo sviluppo di dApp sulla piattaforma Ergo fornendo un linguaggio dichiarativo di alto livello, un runtime di esecuzione, un formato di storage e
a una notazione grafica.
Inizieremo con un alto livello di diagrammi e scenderemo alla specifica di FlowCard.
Diagrammi FlowCard
L'idea alla base dei diagrammi FlowCard si basa sulle seguenti osservazioni: 1) Una box Ergo
è immutabile e può essere spesa solo nella transazione che la utilizza come input. 2) Possiamo
quindi disegnare un flusso di box attraverso le transazioni, in modo che le box che fluiscono in
alla transazione siano spese e quelle che fluiscono fuori siano create e aggiunte all'UTXO. 3) Una
transazione da questa prospettiva è semplicemente un trasformatore di vecchie box in nuove,
preservando i saldi di ERG e token coinvolti.
La figura seguente mostra i principali elementi della transazione Ergo che abbiamo già visto
in precedenza (ora sotto il nome di Diagramma FlowCard).

C'è un significato (semantica) rigorosamente definito dietro ogni elemento del diagramma,
così che il diagramma è una rappresentazione visiva (o una vista) del componente eseguibile
sottostante (chiamato FlowCard).
La FlowCard può essere utilizzata come componente riutilizzabile di un dApp Ergo per creare e avviare la
transazione sulla blockchain Ergo. Discuteremo di questo nelle sezioni a venire.
Ora diamo un'occhiata ai singoli pezzi del diagramma FlowCard uno per uno.
1. Nome e Parametri
Ogni flow card ha un nome e un elenco di parametri tipizzati. Questo è simile a un
template con parametri. Nella figura sopra possiamo vedere la flow card Send che ha cinque parametri.
I parametri sono utilizzati nella specifica.
2. Portafoglio del Contratto
Questo è un elemento chiave della flow card. Ogni box ha uno script di protezione. Spesso è lo
script che controlla una firma rispetto a una chiave pubblica. Questo script è banale in ErgoScript
ed è definito come il template def pk(pubkey: Address) = { pubkey } dove pubkey è
a un parametro di tipo Address. Nella figura, il template dello script è applicato al
parametro pk(sender) e quindi si ottiene un contratto di portafoglio concreto. Pertanto,
pk(sender) e pk(receiver) producono script diversi e rappresentano diversi portafogli
nel diagramma, anche se utilizzano lo stesso template.
Il Portafoglio del Contratto contiene un insieme di tutte le box UTXO che hanno uno script dato derivato
dal template di script dato utilizzando i parametri della flow card. Ad esempio, nella figura, il
template è pk e il parametro pubkey è sostituito dal parametro della flow card sender.
3. Contratto
Anche se un contratto è una proprietà di una box, nel diagramma raggruppiamo le box per i loro
contratti, quindi sembra che le box appartengano ai contratti, piuttosto che i
contratti appartengano alle box. Nell'esempio, abbiamo tre contratti istanziati
pk(sender), pk(receiver) e minerFee. Nota che pk(sender) è l'istanza del
template pk con il parametro concreto sender e minerFee è l'istanza del
contratto predefinito che protegge le box di ricompensa del miner.
4. Nome della Box
Nel diagramma possiamo dare a ogni box un nome. Oltre alla leggibilità del diagramma, utilizziamo anche il
nome come sinonimo di un accesso indicizzato più complesso alla box nel contratto. Ad
esempio, change è il nome della box, che può anche essere utilizzato nelle condizioni di ErgoScript
invece di OUTPUTS(2). Utilizziamo anche i nomi delle box per associare le condizioni di spesa
con le box.
5. Box nel portafoglio
Nel diagramma, mostriamo le box (rettangoli più scuri) come appartenenti ai portafogli dei contratti
(rettangoli più chiari). Ogni tale rettangolo box è collegato a un rettangolo transazione
grigio tramite frecce arancioni o verdi
o entrambe. Una box di output (con una freccia verde in arrivo) può includere molte righe di testo in cui ogni
riga specifica una condizione che deve essere controllata come parte della transazione. La prima
riga specifica la condizione sull'importo di ERG che deve essere collocato nella box. Altre
righe possono assumere una delle seguenti forme:
amount: TOKEN- la box deve contenere il datoamountdel datoTOKENR == value- la box deve contenere il datovaluedel dato registroRboxName ? condition- la box chiamataboxNamedeve controllareconditionnel suo script.
Discutiamo queste condizioni nelle sezioni seguenti.
6. Importo di ERG nella box
Ogni box deve memorizzare un importo minimo di ERG. Questo viene controllato quando la transazione di creazione viene
convalidata. Nel diagramma l'importo di ERG è sempre mostrato come la prima riga (ad esempio B: ERG o B - minErg - txFee). L'assegnazione del tipo di valore B: ERG è facoltativa e può
essere utilizzata per leggibilità. Quando il valore è dato come formula, allora questa formula deve essere
rispettata dalla transazione che crea la box.
È importante comprendere che variabili come amount e txFee non sono proprietà nominate
delle box. Sono parametri dell'intero diagramma e rappresentano alcuni
importi. O in altre parole, sono parametri condivisi tra le transazioni (ad esempio, l'Ordine di Vendita e le transazioni di Scambio dell'esempio DEX qui sotto condividono il parametro tAmt). Quindi
il stesso nome è legato allo stesso valore in tutto il diagramma (questo è dove gli
strumenti aiuterebbero molto). Tuttavia, quando si tratta di convalida su catena di quei valori,
solo le condizioni esplicite contrassegnate con ? vengono trasformate in ErgoScript. Allo
stesso tempo, tutte le altre condizioni vengono garantite fuori catena durante la costruzione della transazione (ad esempio in un'applicazione che utilizza l'API di Appkit) e la convalida della transazione quando viene aggiunta alla
blockchain.
7. Importo di token T
Una box può memorizzare valori di molti token. I token nel diagramma sono nominati e una variabile value
può essere associata al token T utilizzando l'espressione value: T. Il value può
essere dato da formula. Se la formula è preceduta da un nome di box come boxName ? formula,
allora deve anche essere controllata nello script di protezione della box boxName. Questa
specificazione aggiuntiva è molto conveniente perché 1) consente di convalidare il design visivo
automaticamente, e 2) le condizioni specificate nelle box di un diagramma sono sufficienti
per sintetizzare gli script di protezione necessari. (di più su questo
qui sotto in "Da Diagrammi a Contratti ErgoScript")
8. Input Tx
Gli input sono collegati alla transazione corrispondente tramite frecce arancioni. Una freccia di input può avere un'etichetta delle seguenti forme:
name@index- nome facoltativo con un indice cioèfee@0o@2. Questa è una proprietà del
endpoint target della freccia. Il nome è utilizzato nelle condizioni delle box correlate
e l'indexè la posizione della box corrispondente nella collezione INPUTS della
transazione.!action- è una proprietà della sorgente della freccia e fornisce un nome per un percorso di spesa alternativo della box (vedremo questo nell'esempio DEX)
A causa dei percorsi di spesa alternativi, una box può avere molte frecce arancioni in uscita, nel qual caso dovrebbero essere etichettate con azioni diverse.
9. Transazione
Una transazione spende box di input e crea box di output. Le box di input sono date dalle
frecce arancioni e le etichette sono attese per posizionare gli input ai
giusti indici nella collezione INPUTS. Le box di output sono date dalle frecce verdi. Ogni transazione deve preservare un saldo rigoroso dei valori di ERG
(somma degli input == somma degli output) e per ogni token la somma degli input >= la somma
degli output. Il diagramma di design richiede una specifica esplicita dei valori di ERG e token
per tutte le box di output per evitare errori impliciti e garantire una migliore leggibilità.
10. Output Tx
Gli output sono collegati alla transazione corrispondente tramite frecce verdi. Una freccia di output può avere un'etichetta della seguente forma name@index, dove un
nome facoltativo è accompagnato da un indice cioè fee@0 o @2. Questa è una proprietà dell'
endpoint sorgente della freccia. Il nome è utilizzato nelle condizioni delle box correlate e l'index è la posizione della box corrispondente nella collezione OUTPUTS della transazione.
Esempio: Scambio Decentralizzato (DEX)
Ora utilizziamo la notazione sopra descritta per progettare una FlowCard per un dApp DEX. È abbastanza semplice
ma illustra anche tutte le caratteristiche chiave dei diagrammi FlowCard
che abbiamo introdotto nella sezione precedente.
Lo scenario dApp è mostrato nella figura seguente:
Ci sono tre partecipanti (acquirente,
venditore e DEX) dell'app DEX e cinque diversi tipi di transazione, che vengono creati dai
partecipanti. L'acquirente desidera scambiare ergAmt di ERG per tAmt di token TID (o vice
versa, il venditore desidera vendere token TID per ERG, chi invia l'ordine per primo non
ha importanza). Sia l'acquirente che il venditore possono annullare i loro ordini in qualsiasi momento. Il servizio di abbinamento off-chain del DEX
può trovare ordini corrispondenti e creare la transazione Swap per
completare lo scambio.
Il seguente diagramma specifica completamente (e formalmente) tutte e cinque le transazioni che devono
essere create fuori catena dall'app DEX. Specifica anche tutte le condizioni di spesa che
devono essere verificate su catena.

Discutiamo il diagramma FlowCard e la logica di ciascuna transazione in dettaglio:
Transazione Ordine di Acquisto
Un acquirente crea una transazione Buy Order. La transazione spende un importo di E ERG
(che scriveremo E: ERG) da una o più box nel portafoglio pk(buyer). La
transazione crea una box bid con ergAmt: ERG protetta dallo script buyOrder. Lo
script buyOrder è sintetizzato dalla specifica (vedi
qui sotto in "Da Diagrammi a Contratti ErgoScript") manualmente o automaticamente da uno
strumento. Anche se non è necessario definire esplicitamente lo script buyOrder durante
la progettazione, al momento dell'esecuzione la box bid deve contenere lo script buyOrder come
proposizione di protezione (che controlla le condizioni di spesa della box), altrimenti le condizioni
specificate nel diagramma non verranno controllate.
La box change viene creata per bilanciare le somme di input e output della transazione.
La box della commissione di transazione è omessa perché può essere aggiunta automaticamente dagli strumenti. Nella
pratica, tuttavia, il progettista può aggiungere esplicitamente la box della commissione a un diagramma. Copre
i casi di transazioni più complesse (come Swap) in cui ci sono molti modi per pagare
la commissione di transazione.
Annulla Acquisto, Annulla Vendita Transazioni
In qualsiasi momento, l'acquirente può annullare l'ordine inviando la transazione CancelBuy. La
transazione deve soddisfare il contratto di protezione buyOrder che protegge la box bid.
Come puoi vedere nel diagramma, sia le transazioni Cancel che Swap possono spendere la
box bid. Quando una box ha alternative di spesa (o percorsi di spesa), ogni
alternativa è identificata da un nome unico preceduto da ! (!cancel e !swap
per la box bid). Ogni percorso alternativo ha condizioni di spesa specifiche. Nel nostro esempio,
quando la transazione Cancel Buy spende la box bid, la condizione ?buyer deve essere
soddisfatta, che leggiamo come "la firma per l'indirizzo buyer deve essere presentata nella
transazione". Pertanto, solo l'acquirente può annullare l'ordine di acquisto. Questa condizione di "firma"
è richiesta solo per il percorso di spesa alternativo !cancel e non è richiesta per !swap.
Transazione Ordine di Vendita
La transazione Sell Order è simile all'BuyOrder in quanto tratta anche i token oltre agli ERG. La transazione spende E: ERG e T: TID token dal portafoglio del venditore
(specificato come contratto pk(seller)). I due output sono ask e change. Il change
è una box standard per bilanciare la transazione. La box ask conserva tAmt: TID token per lo scambio
e minErg: ERG - l'importo minimo di ERG richiesto in ogni box.
Transazione di Scambio
Questa è una transazione chiave nello scenario dell'app DEX. La transazione ha diverse condizioni di spesa
sulle box di input e quelle condizioni sono incluse negli script buyOrder e
sellOrder (che vengono verificati quando la transazione viene aggiunta alla
blockchain). Tuttavia, nel diagramma quelle condizioni non sono specificate nelle box bid e
ask, ma sono invece definite nelle box di output della transazione.
Questa è una convenzione per migliorare l'usabilità perché la maggior parte delle condizioni si riferisce alle proprietà delle
box di output. Potremmo specificare quelle proprietà nella box bid, ma poi dovremmo
usare espressioni più complesse.
Consideriamo l'output creato dalla freccia etichettata con buyerOut@0. Questa etichetta ci dice
che l'output è all'indice 0 nella collezione OUTPUTS della transazione e
che nel diagramma possiamo riferirci a questa box con il nome buyerOut. Quindi possiamo etichettare
sia la box stessa che la freccia per dare alla box un nome.
Le condizioni mostrate nella box buyerOut hanno la forma bid ? condition, il che significa
che devono essere verificate su catena per spendere la box bid.
Le condizioni hanno il seguente significato:
tAmt: TIDrichiede che la box abbia un importo ditAmtdel tokenTIDR4 == bid.idrichiede che il registro R4 nella box sia uguale all'id della boxbid.script == buyerrichiede che la boxbuyerOutabbia lo script del portafoglio in cui si
trova nel diagramma, cioèpk(buyer)
Proprietà simili sono aggiunte alla box sellerOut, che è specificata per essere all'indice 1
e il nome è dato ad essa utilizzando l'etichetta sulla box stessa, piuttosto che sulla freccia.
La transazione Swap spende due box bid e ask utilizzando il percorso di spesa !swap su entrambe,
ma a differenza di !cancel, le condizioni sul percorso non sono specificate. Qui entrano in gioco i
prefissi bid ? e ask ?. Vengono utilizzati in modo che le condizioni elencate nelle box buyerOut e
sellerOut siano spostate nel percorso di spesa !swap delle box bid e ask
rispettivamente.
Se guardi le condizioni delle box di output, vedrai che specificano esattamente
lo scambio di valori tra i portafogli del venditore e dell'acquirente. L'acquirente ottiene l'importo necessario
di token TID e il venditore ottiene l'importo corrispondente di ERG. La transazione Swap
è creata quando ci sono due box corrispondenti con contratti buyOrder e sellOrder.
Da Diagrammi a Contratti ErgoScript
Ciò che è interessante riguardo alle specifiche FlowCard è che possiamo usarle per generare automaticamente
gli script necessari ErgoTree.
Con il supporto degli strumenti appropriati, questo può essere fatto automaticamente, ma in mancanza di
questo, può essere fatto manualmente. Pertanto, la FlowCard ci consente di catturare e rappresentare visivamente
tutte le scelte di design e i dettagli semantici di un dApp Ergo.
Ciò che faremo ora è creare meccanicamente il contratto buyOrder dalle
informazioni fornite nella flow card DEX.
Ricorda che ogni script è una proposizione (espressione booleana) che deve valutare
come true per consentire la spesa della box. Quando abbiamo molte condizioni da soddisfare contemporaneamente,
possiamo combinarle in una formula logica utilizzando l'operazione binaria AND, e se abbiamo
alternative (non necessariamente esclusive) possiamo metterle nell'operazione OR.
La box buyOrder ha i percorsi di spesa alternativi !cancel e !swap. Pertanto, il
codice ErgoScript dovrebbe avere un'operazione OR con due argomenti - uno per ciascun percorso di spesa.
/** contratto buyOrder */
{
val cancelCondition = {}
val swapCondition = {}
cancelCondition || swapCondition
}
La formula per l'espressione cancelCondition è data nel percorso di spesa !cancel
della box buyOrder. Possiamo includerla direttamente nello script.
/** contratto buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {}
cancelCondition || swapCondition
}
Per il percorso di spesa !swap della box buyOrder, le condizioni sono specificate nella
box di output buyerOut della transazione Swap. Se le includiamo semplicemente nel
swapCondition, otteniamo uno script sintatticamente errato.
/** contratto buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {
tAmt: TID &&
R4 == bid.id &&
@contract
}
cancelCondition || swapCondition
}
Possiamo però tradurre le condizioni dalla sintassi del diagramma in espressioni ErgoScript
utilizzando le seguenti semplici regole:
buyerOut@0==>val buyerOut = OUTPUTS(0)tAmt: TID==>tid._2 == tAmtdovetid = buyerOut.tokens(TID)R4 == bid.id==>R4 == SELF.iddoveR4 = buyerOut.R4[Coll[Byte]].getscript == buyer==>buyerOut.propositionBytes == buyer.propBytes
Nota, nel diagramma TID rappresenta un id di token, ma ErgoScript non ha accesso ai
token per gli id, quindi non possiamo scrivere tokens.getByKey(TID). Per questo motivo, quando il
diagramma viene tradotto in ErgoScript, TID diventa una costante nominata dell'indice nella
collezione tokens della box. Il valore concreto della costante è assegnato quando la
transazione BuyOrder con la box buyOrder viene creata. La corrispondenza e
coerenza tra l'effettivo tokenId, la costante TID e i token effettivi della
box buyerOut è garantita dal codice dell'applicazione fuori catena, che è completamente
possibile poiché tutte le transazioni sono create dall'applicazione utilizzando FlowCard come
specifica guida. Questo può sembrare troppo complicato, ma fa parte della traduzione
dalla specifica del diagramma al codice applicativo eseguibile effettivo, gran parte del quale può essere
automatizzato.
Dopo la trasformazione possiamo ottenere uno script corretto che controlla tutte le precondizioni
richieste per la spesa della box buyOrder.
/** contratto buyOrder */
def DEX(buyer: Addrss, seller: Address, TID: Int, ergAmt: Long, tAmt: Long)
{
val cancelCondition: SigmaProp = { buyer } // verifica la firma dell'acquirente (ProveDlog)
val swapCondition = OUTPUTS.size > 0 && { // garantire l'accesso agli OUTPUTS
val buyerOut = OUTPUTS(0) // da buyerOut@0
buyerOut.tokens.size > TID && { // garantire l'accesso ai token
val tid = buyerOut.tokens(TID)
val regR4 = buyerOut.R4[Coll[Byte]]
regR4.isDefined && { // garantire l'accesso a R4
val R4 = regR4.get
tid._2 == tAmt && // da tAmt: TID
R4 == SELF.id && // da R4 == bid.id
buyerOut.propositionBytes == buyer.propBytes // da script == buyer
}
}
}
cancelCondition || swapCondition
}
Uno script simile per la box sellOrder può essere ottenuto utilizzando le stesse regole di traduzione.
Con l'aiuto degli strumenti, il codice dei contratti può essere generato meccanicamente dalla
specifica del diagramma.
Conclusioni
I modelli di programmazione dichiarativa hanno già vinto la battaglia contro la programmazione imperativa
in molti domini applicativi come Big Data, Stream Processing, Deep Learning, Database,
etc. Ergo è pioniere del modello dichiarativo di sviluppo di dApp come un'alternativa migliore e più sicura
al modello imperativo ora popolare dei contratti intelligenti.
Il concetto di FlowCard sposta l'attenzione dalla scrittura di contratti ErgoScript al
generale flusso di valori (da cui il nome), in modo tale che ErgoScript possa sempre
essere generato da essi. Non dovrai mai guardare il codice ErgoScript una volta che gli strumenti
sono in atto.
Ecco i possibili prossimi passi per il lavoro futuro:
-
Formato di storage per la specifica FlowCard e il corrispondente formato di file standardizzato EIP
(Json/XML/Protobuf). Questo consentirà a vari strumenti (Diagram Editor, Runtime, dApps ecc.) di
creare e utilizzare file*.flowcard. -
Visualizzatore FlowCard, che può generare i diagrammi dai file
*.flowcard. -
Runtime FlowCard, che può eseguire file
*.flowcard, creare e inviare transazioni alla rete Ergo. -
Strumento di Progettazione FlowCard, che può semplificare lo sviluppo di diagrammi complessi. Questo renderà
la progettazione e la convalida dei contratti Ergo un'esperienza piacevole, più simile a disegnare
piuttosto che a codificare. Inoltre, la correttezza dell'intero scenario dApp può essere
verificata e controllata dagli strumenti.
Riferimenti
Share post
13 agosto 2025
9 luglio 2025
12 maggio 2025
7 agosto 2022




















