Blockchain sin intermediarios: cómo enviamos valores a un registro distribuido

Toda la actividad econ√≥mica se basa hist√≥ricamente en intermediarios. Cualquier transacci√≥n, incluso simple entre las dos partes, va acompa√Īada de la participaci√≥n de varios intermediarios: bancos, casas de cambio, c√°maras de compensaci√≥n, etc. La exclusi√≥n de intermediarios probablemente har√≠a que la interacci√≥n sea m√°s eficiente. Entonces, ¬Ņpor qu√© no intentar construir una nueva infraestructura descentralizada sobre la base de blockchain, donde los participantes en la transacci√≥n pueden trabajar directamente? En esta publicaci√≥n, hablaremos sobre c√≥mo comenzamos nuestro viaje hacia dicha infraestructura: desarrollamos transacciones de blockchain y, como resultado, realizamos repos - pr√©stamos de dinero contra valores.



Bonos a corto plazo


Nuestra primera transacción financiera OTC en blockchain fue la emisión de un bono a corto plazo del operador móvil MTS con la participación del Depósito Nacional de Liquidación (NSD). Este es un tipo de "banco central" de todos los depositarios. Los depositarios son intermediarios de infraestructura que mantienen registros de los propietarios de valores y los emiten.

En esa transacción, MTS, al llamar a la función del contrato inteligente, registró en la cadena de bloques una expresión de voluntad de vender valores a Sberbank, y confirmó en la cadena de bloques su acuerdo con los términos de la transacción. Las órdenes contrarias firmadas por ambas partes fueron recibidas por NSD, que las ejecutó en sus sistemas contables. Además, la cadena de bloques mostraba las cuentas de los participantes de la transacción en valores y dinero.

En ese proyecto, seleccionamos la plataforma Hyperledger Fabric 1.1 de c√≥digo abierto, dise√Īada para crear soluciones de blockchain empresariales cerradas. Las cadenas de bloques p√ļblicas no son adecuadas aqu√≠, porque debemos garantizar la privacidad de los datos. Enfrentamos tales limitaciones en el piloto de factoring de Sberbank con M. Video, que se implement√≥ en la cadena de bloques Ethereum. Por el contrario, Hyperledger Fabric le permite colocar a todos los participantes en una transacci√≥n en un canal dedicado, donde pueden intercambiar cualquier informaci√≥n necesaria y procesarla con contratos inteligentes con todas las funciones.

El c√≥digo fuente del proyecto de emisi√≥n de bonos MTS se subi√≥ p√ļblicamente a GitHub. Sin siquiera entrar en el algoritmo de trabajo, puede comprender que en el ciclo de vida de una transacci√≥n, la cadena de bloques recibi√≥ un papel bastante modesto como transporte de √≥rdenes de compensaci√≥n. Por otro lado, sobre la base de estas instrucciones, los saldos de las cuentas cambiaron, por lo que desde el punto de vista de la l√≥gica empresarial, esto fue m√°s interesante que un simple servicio de gesti√≥n de documentos electr√≥nicos.

La principal ventaja de la soluci√≥n era la versatilidad. El esquema de ‚Äúdos contrapartes y un registrador‚ÄĚ cubre casi cualquier transacci√≥n en el mercado OTC, y con cambios menores, la mayor√≠a de las transacciones comerciales en general.

REPO 1.0


En un nuevo proyecto en la cadena de bloques, decidimos mostrar cómo implementar un acuerdo de recompra en un sistema descentralizado: un préstamo de dinero contra valores. Por lo general, estas y otras transacciones OTC pasan por intermediarios: depositarios, cámaras de compensación, corredores.

En este proyecto, celebramos un acuerdo de recompra entre Sberbank y un socio extranjero. Ya utilizaba Hyperledger Fabric versión 1.2. En comparación con los bonos MTS, tuvimos dos diferencias:

  • Solo dos participantes en la transacci√≥n se conectaron a la cadena de bloques, cuyos depositarios, Euroclear y Clearstream, recibieron todos los pedidos a trav√©s de los canales tradicionales de transmisi√≥n de datos desde las oficinas administrativas de Sberbank y su contraparte.
  • En el contrato inteligente, implementamos una l√≥gica comercial compleja: las cotizaciones diarias de la seguridad que sirvieron como garant√≠a para el pr√©stamo se descargaron a la cadena de bloques, y el contrato inteligente calcul√≥ la necesidad y el monto del reembolso anticipado, teniendo en cuenta el costo modificado de la garant√≠a, el descuento, el calendario de los intercambios de salida y otros par√°metros. Tal sincronizaci√≥n P2P de algoritmos de c√°lculo entre participantes no se puede obtener sin un registro distribuido. Esto es mucho m√°s conveniente que un c√°lculo independiente de obligaciones y montos por cada lado: sin reconciliaciones que requieren mucho tiempo, sin confirmaciones.

Entre contrapartes organizó un chat y flujo de trabajo dentro del canal. Los datos sobre ellos se almacenaron en la cadena de bloques. Después de cada cambio en el registro distribuido, los miembros del canal recibieron una alerta por correo electrónico.

"REPO 1.0" trabajamos desde el lado legal. Con la ayuda de una gran firma de abogados, se realizó un análisis de los casos del Tribunal Superior de Londres. Además, el EDS del banco y su contraparte utilizaron diferentes algoritmos criptográficos.

¬ŅC√≥mo funciona REPO 1.0?


Cada parte de la transacción tiene su propio nodo blockchain. Todos los nodos están conectados entre sí en una red P2P. Supongamos que necesita hacer un trato. Implementamos un contrato inteligente entre las partes de la transacción, donde se describe completamente el instrumento financiero.



Despu√©s de la creaci√≥n del contrato de nuestra parte, el comerciante lo firma. El cliente tambi√©n revisa y firma el contrato. Luego se revisan y verifican las firmas. En este caso, la transacci√≥n se realiz√≥ bajo la ley inglesa, los datos de la firma digital electr√≥nica se ingresaron en el documento GMRA. Para la firma del cliente, se requiere verificaci√≥n de que una persona autorizada est√© presente en el certificado de firma. Finalmente, el cliente acepta el contrato y acepta todas las condiciones. Puede adjuntar cualquier n√ļmero de documentos a un contrato firmado.

Después de eso, el contrato recibe el estado de "en el trabajo". El contrato "en curso" se recalcula automáticamente al cargar nuevos precios de mercado. Si hay un valor en el contrato, se toma el precio de mercado, se recalcula el Préstamo a Valor (LTV): la relación entre el monto del préstamo y el valor del valor en valores. LTV es uno de los términos clave en una transacción de repos, su significado se prescribe en el contrato. El precio de las acciones ha aumentado considerablemente, y el LTV se está volviendo menor que el indicado en GMRA (en lo que respecta a la ley inglesa). En consecuencia, el banco devuelve valores al cliente (como una de las opciones), ya que teniendo en cuenta los nuevos precios, resulta que el banco tiene una mayor seguridad.

Pero si LTV se hace más grande, entonces el programa le permite imprimir un aviso colateral, una notificación al cliente sobre la necesidad de hacer seguridad adicional (acciones o dinero) para que el valor de LTV vuelva al valor inicial. Anteriormente, la notificación colateral solo podía enviarse por correo, se creaban documentos separados para esto y durante la creación de estos documentos, LTV podía cambiar nuevamente. Ahora que vemos los mismos cálculos con el cliente en línea, podemos interactuar fácilmente.

Además, el programa todos los días fija el precio de la recompra de valores, teniendo en cuenta los intereses. Si el cliente no está de acuerdo con él al cargar el precio de mercado, mira el registro de recálculo completo: qué fue, qué se convirtió, qué precio se cargó, de dónde vino. Y luego comienza la discusión del chat.

REPO 2.0


Quer√≠amos que nuestro REPO en la cadena de bloques pudiera iniciar el movimiento de activos reales en funci√≥n de nuestra l√≥gica interna. Pero en REPO 1.0, debido a las dificultades organizativas para conectar los dep√≥sitos occidentales, a√ļn no hemos podido lograrlo. Entonces comenzamos el nuevo piloto Repo 2.0. Ten√≠a dos objetivos:

  • La transacci√≥n debe realizarse con la participaci√≥n de dos partes y el depositario, para aprovechar al m√°ximo la infraestructura del proyecto de bonos MTS.
  • La cadena de bloques debe estar facultada para volver a evaluar la garant√≠a y configurar una llamada de margen que podr√≠a ser ejecutada autom√°ticamente por un dep√≥sito conectado a una red distribuida.

NSD inmediatamente quiso conectarse al proyecto. Para aterrizar una transacción iniciada en blockchain en el campo conservador de las leyes federales que rigen el mercado financiero nacional, trabajamos con abogados para un acuerdo complementario de cinco páginas para el acuerdo de gestión de documentos electrónicos. Fue firmado por todas las partes de la transacción y NSD.

NSD actuó como cámara de compensación en esta transacción. Realizó todas las instrucciones sobre el movimiento de fondos y valores. Esta transacción se concluyó bajo la ley rusa.

El cliente aceptó el contrato con una firma electrónica. Luego, el acuerdo fue aceptado por Sberbank con su firma: verificó el cumplimiento de todos los parámetros con los valores necesarios y la autoridad de la persona que aceptó del cliente. Después de eso, el contrato entró en funcionamiento. NSD subió datos de mercado, recálculo de contrato inteligente.

¬ŅC√≥mo funciona REPO 2.0?


Para implementar la red e interactuar con la interfaz del cliente con el código de cadena, utilizamos la solución Fabric Starter . En lugar de la interfaz grpc estándar para HLF, proporciona una API REST, que en nuestro caso redujo significativamente la complejidad de la integración.



La red subió de la siguiente manera. Cada uno de los tres lados después de la preinstalación en el servidor Docker lanzó Fabric Starter, que creó contenedores con los componentes del nodo. Estos componentes incluían un par externo para interactuar con otras organizaciones y un servicio API REST a través del cual el nodo interactuaba con la aplicación cliente. En el lanzamiento de Starter, la red blockchain también se configuró y se creó un canal privado en el que se instaló el código de la cadena con la política de respaldo. En nuestro caso, cada transacción debe tener las firmas de los tres participantes.

Durante la fase de prueba, Docker Swarm se utilizó para organizar la conexión de los servidores de los participantes, sin embargo, con el fin de hacer un trato real, cambiaron a DNS. La plataforma en sí es responsable del transporte de mensajes; los datos se transmiten a través de Internet con cifrado TLS.

El aspecto técnico del problema.


El proceso de desarrollo de una aplicación distribuida en HLF comienza de manera bastante tradicional, con estructuras de datos y un código de cadena (de hecho, un conjunto de procedimientos almacenados), cuya llamada conduce al almacenamiento, modificación o lectura de estas estructuras desde el libro mayor. La plataforma permite el uso de varios lenguajes de programación para el desarrollo de códigos de cadena y DBMS para almacenamiento local. Preferimos Go y CouchDB, respectivamente.

La esencia central de los proyectos de repos en nuestro modelo de datos es el contrato en sí y sus obligaciones subsidiarias. Fueron creados para cada uno de los dos pilotos, así como para llamadas de margen. Esta arquitectura fue un paso adelante en comparación con el modelo de enlace MTS, que se basó en la esencia de la "Orden". También se crearon objetos independientes para valores, que por lo tanto se tokenizaron parcialmente. Pero al desarrollar el experimento con la administración de cuentas y la tokenización virtual de dinero, decidimos posponer una de las próximas versiones de la solución.

Las principales funciones de nuestra solución:

  • Crea un contrato.
  • Firme un contrato con su EDS confirmando la aceptaci√≥n de los t√©rminos del contrato.
  • Descargue los precios de mercado y comience a recalcular el valor colateral. Su desviaci√≥n del umbral establecido provoc√≥ la creaci√≥n de una nueva obligaci√≥n de llamada de margen.
  • Reflejar el estado de la obligaci√≥n.

En el aspecto técnico, el procedimiento de reevaluación es más interesante aquí. Analicémoslo con más detalle.

En el proceso comercial, el procedimiento debe iniciarse una vez al día, después de que Oracle (en la prueba piloto de "REPO 2.0" realizada por NSD) cargó las cotizaciones actualizadas de valores en el sistema.

func (t *CIBContract) recalculationData(stub shim.ChaincodeStubInterface, loadData *loadDataType, curDay string) pb.Response {...} 

El ciclo principal del procedimiento pasa por todos los valores para los que se han actualizado las cotizaciones.

 for _, securities := range loadData.Securities {...} 

A continuación, se realizan varios controles. Por ejemplo, si el intercambio con el que se recibieron los datos del mercado es hoy un día libre, entonces el recuento no debería ocurrir.

 if t.checkHoliday(stub, contract.Settings.Calendars) == "yes" { hisYes := historyType{curDay, "LoadData. Calendar", "System", "LoadData. Today is holiday ! No load market data to contract !"} ... contract.History = append(contract.History, hisYes) … err = stub.PutState(contrID, contractJSONasBytes) } 

Para calcular el precio del bono actualizado, el rendimiento del cupón acumulado (NDC) se agrega al precio neto cargado. El piloto implementó el soporte para el esquema 30/360 para calcular NKD.

 priceIzm = float64(securities.Price + float64(securities.CouponRate)*float64((int(settlementDate.Year()) - int(dateStart.Year()))*360 + (int(settlementDate.Month()) - int(dateStart.Month()))*30 + (int(settlementDate.Day()) - int(dateStart.Day())))*100/360/100) curCurrVal = priceIzm 

Si la moneda de la transacción es diferente de la moneda en la que se cotiza el valor, se realiza una conversión de cambio.

 if contract.GeneralTerms.PurchasePrice.Currency != securities.Currency { curCurrName = securities.Currency + "-" + contract.GeneralTerms.PurchasePrice.Currency               for _, currency := range loadData.Currencies {              if currency.Name == curCurrName {                           curCurrVal = priceIzm * currency.Value } } } 

Ahora necesitamos calcular LTV. Mantenga el antiguo valor del coeficiente para la historia.

 oldCurLTV := contract.MarginingTerms.CurrentLTV 

Es necesario tener en cuenta las llamadas de margen ejecutadas durante la vida de la transacción. Los requisitos pueden provenir de ambos lados y en dos formas:

  • Valores El prestatario otorga seguridad adicional en caso de una ca√≠da en el precio de mercado de la seguridad. El acreedor devuelve parte de la garant√≠a en caso de aumento de precios.
  • Dinero El prestatario antes de lo programado paga la parte del pr√©stamo que ha dejado de estar cubierta por una garant√≠a m√°s barata. El prestamista aumenta el monto del pr√©stamo en respuesta a un aumento en el valor de la garant√≠a.

En el primer caso, la cantidad de valores en la garantía simplemente se actualiza. Y en caso de ganar dinero con ellos, también es necesario acumular la rentabilidad especificada en los términos adicionales de la transacción.

 for _, addCollateral := range contract.MarginingTerms.AddCollateral { currSumCollateral := addCollateral.Sum + (addCollateral.Sum*contract.MarginingTerms.RateOnCashMargin*float64(deltaColDate) / float64(contract.MarginingTerms.Basis))/100 ... allSumCollateral = allSumCollateral + currSumCollateral ... ht := historyType{curDay, System", "LoadData. Recalculation data(addCollateral) Contract " + contrID + " - currSumCollateral: " + strconv.FormatFloat(float64(currSumCollateral), 'f', 2, 64) ... }        ... contract.History = append(contract.History, ht) } 

Calculamos el monto total de la recompra; de hecho, este es el monto del préstamo con intereses, que debemos pagar.

 rePurchasePriceCur := contract.GeneralTerms.PurchasePrice.Sum + (contract.GeneralTerms.PurchasePrice.Sum*contract.GeneralTerms.RepoRate*float64(deltaSigningDate)/float64(contract.MarginingTerms.Basis))/100 

Ahora calculamos el coeficiente LTV. Para hacer esto, reste el valor en efectivo del precio de recompra y divida el valor resultante por el valor total de los valores en el valor. Los montos acreditados por el acreedor est√°n marcados con un "-" y se agregar√°n al precio de recompra.

 contract.MarginingTerms.CurrentLTV = (rePurchasePriceCur - allSumCollateral) * float64(100) / (float64(contract.GeneralTerms.PurchasedSecurities.Quantity) * curCurrVal) 

Finalmente, calculamos los desencadenantes en el contrato. El mismo procedimiento creará objetos de orden de llamada de margen si el valor de LTV se desvía del corredor especificado.

 contract = t.checkTriggerEvents(stub, "LoadData", contract, curDay, securities) 

Y escriba información en el historial para mostrarla en la interfaz de usuario.

 ht := historyType{curDay, "System", "LoadData. Recalculation data(change curLTV, ADTV) Contract " + contrID + " - oldCurLTV: " + strconv.FormatFloat(float64(oldCurLTV), 'f', 2, 64) + ", newCurLTV: " + strconv.FormatFloat(float64(contract.MarginingTerms.CurrentLTV), 'f', 2, 64)...} contract.History = append(contract.History, ht) 

Para resumir


Tal esquema puede funcionar no solo con valores y contratos, sino tambi√©n en otros escenarios. Por ejemplo, con los suministros de electricidad, donde hay diferentes tarifas, diferentes conexiones en diferentes momentos. O con la factorizaci√≥n: pr√©stamos a proveedores por se√Īales de env√≠o de mercanc√≠as. Hay muchos casos de usuarios en econom√≠a, cuando todos usan sus propias fuentes de datos que deben verificarse.

Nuestro objetivo es crear una red que conecte a los bancos entre sí y a sus clientes en todo el país, y que use contratos inteligentes para describir en él contratos no de criptografía, sino de la economía tradicional: instrumentos financieros. Dicha red será estable, abierta y, como debería estar en una red P2P, aquí nadie tendrá un estado especial.

Source: https://habr.com/ru/post/442692/


All Articles