Ofertele susținute de active sunt o propunere de rezolvare a problemei, care s-ar putea ca ofertele din registru să nu fie executabile.

master

Ofertele susținute de active sunt o propunere de rezolvare a problemei conform cărora un singur cont ar putea avea datorii, sub formă de oferte în registru, care depășește activele contului. Când se întâmplă acest lucru, ofertele din registrul s-ar putea să nu fie executabile, în sensul că nu există nicio ofertă de trecere astfel încât să fie schimbată întreaga sumă a ofertei. Ofertele din registru care nu sunt executabile oferă un fals sentiment de lichiditate.

Vom spune că o ofertă este „executabilă imediat în totalitate” (pe scurt IEIF) dacă, dacă ar fi traversată de o ofertă ipotetică fără limite cu privire la suma cumpărată sau vândută, întreaga sumă a activului de vânzare ar fi schimbată. Este de dorit ca toate ofertele să fie IEIF, deoarece acest lucru permite utilizatorilor să evalueze cu ușurință cantitatea de lichiditate disponibilă.

Protocolul impune ca, la crearea, fiecare ofertă să îndeplinească următoarele două condiții:

  • Suma oferită pentru vânzare nu depășește soldul disponibil al activului de vânzare
  • Suma oferită pentru cumpărare (calculată implicit) nu depășește limita disponibilă a activului de cumpărare

Vom demonstra acum că aceste condiții nu sunt suficiente pentru a ne asigura că o ofertă este IEIF. Să presupunem că un cont creează o ofertă care este IEIF cu suma de vânzare egală cu soldul disponibil al activului de vânzare. Contul creează apoi o a doua ofertă cu un preț mai slab, dar altfel identic cu prima. Deși fiecare ofertă îndeplinește individual cerințele de mai sus, a doua ofertă nu este IEIF. Să presupunem că a doua ofertă a fost traversată de o ofertă ipotetică fără limite. Această ofertă de trecere ar traversa inițial prima ofertă, care nu lasă sold disponibil pentru activul de vânzare. Atunci când a doua ofertă este apoi încrucișată, nu se pot schimba active.

Analog cu exemplul de mai sus, este posibil să creați oferte multiple care îndeplinesc în mod individual cerințele, dar care depășesc limita disponibilă atunci când sunt luate în considerare în total. Să presupunem că o ofertă creează o ofertă care este IEIF cu suma de cumpărare egală cu limita disponibilă a activului de cumpărare. Contul creează apoi o a doua ofertă cu un preț mai slab, dar altfel identic cu prima. Deși fiecare ofertă îndeplinește individual cerințele de mai sus, a doua ofertă nu este IEIF. Să presupunem că a doua ofertă a fost traversată de o ofertă ipotetică fără limite. Această ofertă de traversare ar trece inițial de prima ofertă, care nu lasă nicio limită disponibilă pentru activul de cumpărare. Atunci când a doua ofertă este apoi încrucișată, nu se pot schimba active.

Această propunere va necesita modificări XDR pentru AccountEntry și TrustLineEntry, precum și actualizări de schemă pentru conturi și tabele cu linii de încredere. Actualizarea XDR este:

SQL necesar pentru actualizarea schemei este:

De asemenea, trebuie adăugat codul rezultatului operației ACCOUNT_MERGE_DEST_FULL:

Scopul propunerii de oferte susținute de active este de a menține invariantul că fiecare ofertă este IEIF. Începem cu o discuție despre ceea ce poate face ca ofertele să nu mai fie IEIF:

Din această analiză, este clar că orice propunere care încearcă să modifice sau să șteargă oferte care nu mai sunt IEIF ar necesita menținerea cărții de oferte după încasarea taxelor și după fiecare operațiune. Acest lucru ar fi atât complicat, cât și ineficient. În schimb, urmărim o propunere care modifică operațiunile astfel încât să garanteze că ofertele rămân IEIF. Pentru a realiza acest lucru, mai întâi definim cantități noi care sunt date derivate din registru:

  • cont.vanzareDatoriu
    • Pentru contul A: suma activului nativ oferit pentru a fi vândut, cumulat la toate ofertele deținute de A
  • account.buyingDatorii
    • Pentru contul A: suma activului nativ oferit pentru a fi cumpărat, cumulat la toate ofertele deținute de A
  • linie de încredere.vânzareDatoriu
    • Pentru contul A și activul nativ X: suma de X oferită pentru a fi vândută, agregată la toate ofertele deținute de A
  • linia de încredere.cumpărareaDatorilor
    • Pentru contul A și activul nativ X: suma de X oferită pentru a fi cumpărată, cumulată la toate ofertele deținute de A

Aceste cantități vor fi actualizate ori de câte ori o ofertă este creată, modificată sau ștearsă. Când se creează o ofertă, pasivele pentru ofertă vor fi calculate și adăugate la pasivele de cumpărare și pasivele de vânzare în contul relevant și/sau liniile de încredere. Atunci când o ofertă este ștearsă, pasivele pentru ofertă vor fi calculate și scăzute din pasivele de cumpărare și pasivele din contul relevant și/sau liniile de încredere. Când o ofertă este modificată, aceasta poate fi vizualizată ca o ștergere urmată de o creație, astfel încât pasivele de cumpărare și Pasivele de vânzare pot fi actualizate utilizând logica din aceste cazuri. Deoarece încărcăm deja conturi și linii de încredere atunci când interacționăm cu oferte, costul menținerii acestor cantități ar trebui să fie minim.

Acum vom folosi aceste cantități pentru a modifica operațiunile astfel încât să garanteze că ofertele rămân IEIF. În cele ce urmează, limita disponibilă este INT64_MAX pentru activul nativ și limita - CumpărarePasive pentru active non-native. În mod similar, soldul disponibil este sold - rezervă - vânzare Datorii pentru active native și sold - vânzare Datorii pentru active non-native. Pentru ca emitenții să poată cumpăra sau vinde orice cantitate (chiar depășind INT64_MAX) dintr-un activ pe care l-au emis, limita disponibilă și soldul disponibil vor fi întotdeauna INT64_MAX în acest caz. Propunerea de oferte susținute de active modifică operațiunile astfel încât toate ofertele să rămână IEIF după o operațiune:

Comportamentul ManageOfferOp (și CreatePassiveOfferOp) va suferi o schimbare considerabilă pentru a face comportamentul previzibil și performant în ceea ce privește pasivele. Înainte de a traversa orice ofertă, ambele operațiuni vor aplica acum următoarele cerințe:

  • Dacă modificați ID-ul ofertei de ofertă, atunci obligațiile asociate cu ID-ul ofertei de ofertă sunt eliminate
  • Dacă se creează o nouă ofertă, numărul de subintrări este actualizat
  • Dacă pasivele de cumpărare asociate cu noua ofertă depășesc limita disponibilă, atunci operațiunea eșuează cu MANAGE_OFFER_LINE_FULL
  • Dacă pasivele de vânzare asociate cu noua ofertă depășesc soldul disponibil, atunci operațiunea eșuează cu MANAGE_OFFER_UNDERFUNDED

Aceste actualizări la ManageOfferOp (și CreatePassiveOfferOp) implică toate modificările discutate în lista anterioară pentru aceste operațiuni.

Vom denota versiunea de protocol care activează această propunere ca PROPOSAL_VERSION. Schema bazei de date poate fi actualizată pentru a include Datorii de cumpărare și Datorii de vânzare, unde aceste valori sunt setate la NULL până când versiunea protocolului este cel puțin PROPOSAL_VERSION .

Actualizarea versiunii protocolului

Când versiunea protocolului este actualizată la PROPOSAL_VERSION, valorile de CumpărareDatoriu și de vânzareDatoriu vor trebui calculate pentru toate conturile care dețin oferte. Pentru alte conturi, aceste valori pot fi lăsate ca NULL și actualizate leneș, sau pot fi actualizate global la 0. Ar fi mai bine să actualizăm leneș valorile deoarece acest lucru ar necesita o bucket mult mai mică decât actualizarea globală la 0.

Abordare alternativă: ștergeți toate ofertele existente

După cum sugerează descrierea, această abordare ar șterge toate ofertele existente atunci când protocolul este actualizat la PROPOSAL_VERSION. Începând cu registrul 18178688, există 12734 oferte deținute de 2653 de conturi (dintr-un total de 474454 de conturi). Un dezavantaj al acestei abordări este că ar provoca probabil o scădere considerabilă a lichidității disponibile pentru o perioadă de timp, în timp ce sunt create noi oferte. Unele oferte care au fost create aparțin unor conturi care nu ar putea să le recreeze. Există 5 oferte deținute de 4 conturi fără semnatari și o greutate cheie principală de 0, 2 dintre aceste oferte vândând un activ emis de cont. Există o altă ofertă deținută de un cont a cărui pondere totală a semnatarilor și a cheii principale nu depășește pragul mediu și vinde și un activ emis de cont. Merită să repetăm ​​că aceasta este doar o limită inferioară simplă a numărului de oferte care nu au putut fi recreate.

Secțiunea anterioară detaliază doar un singur punct de incompatibilitate înapoi, dar procesul de creștere a rezervei de bază prezintă o problemă similară a incompatibilității înapoi, care ar fi posibilă în mod repetat în viitor. Motivul pentru aceasta este că creșterea rezervei de bază ar putea determina ca ofertele de vânzare a activului nativ să nu mai fie IEIF. Soluțiile potențiale prezentate în secțiunea anterioară s-ar aplica și aici, dar aceleași dezavantaje s-ar aplica și ele.

  • Cumpărarea de pasive și vânzarea Pasivele sunt actualizate atunci când ofertele sunt modificate de PathPaymentOp, ManageOfferOp, CreatePassiveOfferOp și AllowTrustOp
  • Fiecare operație ar trebui să aibă noul comportament descris mai sus

Confirmarea corespondentă este git: 4dab9625d42b252d3f11500151ffcc66a1cd5ad2