Aplikasyon nan kont Waves entelijan: soti nan vann piblik nan pwogram bonis

Aplikasyon nan kont Waves entelijan: soti nan vann piblik nan pwogram bonis

Blockchain souvan asosye sèlman ak lajan kript, men domèn aplikasyon teknoloji DLT yo pi laj. Youn nan zòn ki pi pwomèt pou itilize nan blockchain se yon kontra entelijan ki egzekite otomatikman epi ki pa mande pou konfyans ant pati yo ki te antre nan li.

RIDE - yon lang pou kontra entelijan

Waves te devlope yon lang espesyal pou kontra entelijan - RIDE. Dokiman konplè li yo sitiye isit la. Epi isit la - atik sou sijè sa a sou Habr.

Kontra RIDE a se yon predi epi li retounen "vre" oswa "fo" kòm rezilta. An konsekans, tranzaksyon an swa anrejistre nan blockchain la oswa rejte. Kontra a entelijan konplètman garanti pwogrè nan kondisyon espesifye. Gen tranzaksyon nan yon kontra nan RIDE kounye a pa posib.

Jodi a gen de kalite kontra entelijan Waves: kont entelijan ak byen entelijan. Yon kont entelijan se yon kont itilizatè regilye, men yo mete yon script pou li ki kontwole tout tranzaksyon yo. Yon script kont entelijan ta ka sanble tankou sa a, pou egzanp:

match tx {
  case t: TransferTransaction | MassTransferTransaction => false
  case _ => true
}

tx se yon tranzaksyon ke nou pèmèt nou sèvi ak mekanis matche modèl sèlman si se pa yon tranzaksyon transfè. Yo itilize matche modèl nan RIDE pou tcheke kalite tranzaksyon an. Tout kont ki deja egziste yo ka trete nan script kont entelijan an kalite tranzaksyon yo.

Script la kapab tou deklare varyab, sèvi ak "si-lè sa a-lòt" konstwi ak lòt metòd pou konplètman tcheke kondisyon yo. Pou asire ke kontra yo gen konplè ak konpleksite (pri) ki fasil pou prevwa anvan egzekisyon kontra a kòmanse, RIDE pa genyen bouk oswa deklarasyon so.

Lòt karakteristik nan kont Waves gen ladan prezans nan yon "eta," se sa ki, eta a nan kont la. Ou ka ekri yon kantite enfini pè (kle, valè) nan eta kont la lè l sèvi avèk tranzaksyon done (DataTransaction). Lè sa a, enfòmasyon sa yo ka trete tou de atravè API REST la ak dirèkteman nan kontra entelijan an.

Chak tranzaksyon ka genyen yon seri prèv, kote yo ka antre siyati patisipan an, ID tranzaksyon ki nesesè yo, elatriye.

Travay ak RIDE via Id pèmèt ou wè gade konpile nan kontra a (si li se konpile), kreye nouvo kont epi mete Scripts pou li, osi byen ke voye tranzaksyon atravè liy lan lòd.

Pou yon sik konplè, ki gen ladan kreye yon kont, enstale yon kontra entelijan sou li ak voye tranzaksyon, ou ka itilize tou yon bibliyotèk pou kominike avèk API REST (pa egzanp, C#, C, Java, JavaScript, Python, Rust, Elixir) . Pou kòmanse travay ak IDE a, jis klike sou bouton NOUVO.

Posiblite yo pou itilize kontra entelijan yo laj: soti nan entèdi tranzaksyon yo nan sèten adrès ("lis nwa") nan dApps konplèks.

Koulye a, ann gade nan egzanp espesifik nan itilizasyon kontra entelijan nan biznis: lè w ap fè vann piblik, asirans, ak kreye pwogram lwayote.

Rancher

Youn nan kondisyon yo pou yon vann piblik siksè se transparans: patisipan yo dwe gen konfyans ke li enposib manipile òf. Sa a ka reyalize gras a blockchain a, kote done imuiabl sou tout parye ak lè yo te fè yo ap disponib pou tout patisipan yo.

Sou blòk Waves, òf yo ka anrejistre nan eta kont vann piblik atravè DataTransaction.

Ou kapab tou fikse lè kòmanse ak fen vann piblik la lè l sèvi avèk nimewo blòk: frekans jenerasyon blòk nan blòk Waves a apeprè egal a. 60 segonn.

1. angle monte vann piblik pri

Patisipan yo nan yon vann piblik angle mete òf nan konpetisyon youn ak lòt. Chak nouvo parye dwe depase anvan an. Vann piblik la fini lè pa gen plis soumissionnè ki depase dènye òf la. Nan ka sa a, moun ki pi wo a dwe bay kantite lajan an.

Genyen tou yon opsyon vann piblik kote vandè a fikse yon pri minimòm pou anpil la, epi pri final la dwe depase li. Sinon, anpil la rete envann.

Nan egzanp sa a, nou ap travay ak yon kont ki kreye espesyalman pou vann piblik la. Dire vann piblik la se 3000 blòk, ak pri a kòmanse nan lot la se 0,001 WAVES. Yon patisipan ka mete yon òf lè li voye yon DataTransaction ak "pri" kle a ak valè òf la.

Pri a nan nouvo òf la dwe pi wo pase pri aktyèl la pou kle sa a, epi patisipan an dwe gen omwen [new_bid + komisyon] marqueur nan kont li. Adrès machandè a dwe anrejistre nan jaden "sender" nan DataTransaction la, epi wotè blòk òf aktyèl la dwe nan peryòd vann piblik la.

Si nan fen vann piblik la patisipan an te fikse pri ki pi wo a, li ka voye yon Tranzaksyon Echanj pou peye pou lot ki koresponn lan nan pri a espesifye ak pè lajan.

let startHeight = 384120
let finishHeight = startHeight + 3000
let startPrice = 100000
 
#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
match tx {
case d : DataTransaction =>
  #проверяем, задана ли в стейте цена
  let currentPrice = if isDefined(getInteger(this, "price"))
 
                      #извлекаем цену из стейта
                      then extract(getInteger(this, "price"))
                      else startPrice
 
  #извлекаем цену из транзакции
  let newPrice = extract(getInteger(d.data, "price"))
  let priceIsBigger = newPrice > currentPrice
  let fee = 700000
  let hasMoney = wavesBalance(tx.sender) + fee >= newPrice
 
  #убеждаемся, что в текущей транзакции два поля и что отправитель совпадает с указанным в транзакции
  let correctFields = size(d.data) == 2 &&      
      d.sender == addressFromString(extract(getString(d.data,"sender")))
  startHeight <= height && height <= finishHeight && priceIsBigger && hasMoney && correctFields
case e : ExchangeTransaction =>
  let senderIsWinner = e.sender == addressFromString(extract(getString(this, "sender"))) #убеждаемся, что лот обменивает тот, кто его выиграл
  let correctAssetPair = e.sellOrder.assetPair.amountAsset == token && ! isDefined(e.sellOrder.assetPair.priceAsset)
  let correctAmount = e.amount == 1
  let correctPrice = e.price == extract(getInteger(this, "price"))
 
  height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice
case _ => false
}

2. Olandè vann piblik nan diminye pri

Nan yon vann piblik Olandè, yo ofri yon anpil nan yon pri ki pi wo pase sa achtè a vle peye. Pri a diminye etap pa etap jiskaske youn nan patisipan yo dakò achte anpil nan pri aktyèl la.

Nan egzanp sa a nou itilize konstan yo menm jan ak nan anvan an, osi byen ke etap pri a lè delta diminye. Script kont la tcheke si patisipan an se vre premye moun ki mete yon parye. Sinon, DataTransaction a pa aksepte pa blockchain la.

let startHeight = 384120
let finishHeight = startHeight + 3000
let startPrice = 100000000
let delta = 100
 
#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
match tx {
case d : DataTransaction =>
  let currentPrice = startPrice - delta * (height - startHeight)
 
  #извлекаем из поступившей дата-транзакции поле "price"
  let newPrice = extract(getInteger(d.data, "price"))
 
  #убеждаемся, что в стейте текущего аккаунта не содержится поля "sender"
  let noBetsBefore = !isDefined(getInteger(this, "sender"))
  let fee = 700000
  let hasMoney = wavesBalance(tx.sender) + fee >= newPrice
 
  #убеждаемся, что в текущей транзакции только два поля
  let correctFields = size(d.data) == 2 && newPrice == currentPrice && d.sender == addressFromString(extract(getString(d.data, "sender")))
  startHeight <= height && height <= finishHeight && noBetsBefore && hasMoney && correctFields
case e : ExchangeTransaction =>
 
  #убеждаемся, что отправитель текущей транзакции указан в стейте аккаунта по ключу sender
  let senderIsWinner = e.sender == addressFromString(extract(getString(this, "sender")))
 
  #убеждаемся, что аmount ассета указан корректно, и что прайс-ассет - waves
  let correctAssetPair = e.sellOrder.assetPair.amountAsset == token && ! isDefined(e.sellOrder.assetPair.priceAsset)
  let correctAmount = e.amount == 1
  let correctPrice = e.price == extract(getInteger(this, "price"))
  height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice
case _ => false
}

3. Vann piblik "tout-peye"

"All-pay" se yon vann piblik kote tout patisipan yo peye òf la, kèlkeswa ki moun ki genyen lot la. Chak nouvo patisipan peye yon òf, epi patisipan ki fè òf maksimòm lan genyen lot la.

Nan egzanp nou an, chak patisipan vann piblik mete yon òf atravè DataTransaction ak (kle, valè)* = ("gayan", adrès), ("pri", pri). Sa a yon DataTransaction apwouve sèlman si patisipan sa a deja gen yon Transfè Tranzaksyon ak siyati l 'ak òf li a pi wo pase tout sa yo anvan yo. Vann piblik la ap kontinye jiskaske yo rive nan fenHeight.

let startHeight = 1000
let endHeight = 2000
let this = extract(tx.sender)
let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
match tx {
 case d: DataTransaction =>
   #извлекаем из поступившей дата-транзакции поле "price"
   let newPrice = extract(getInteger(d.data, "price"))
 
   #извлекаем из пруфов транзакции публичный ключ аккаунта
   let pk = d.proofs[1]
   let address = addressFromPublicKey(pk)
 
   #извлекаем транзакцию доказательство из пруфов поступившей дата транзакции
   let proofTx = extract(transactionById(d.proofs[2]))
   
   height > startHeight && height < endHeight
   && size(d.data) == 2
   #убеждаемся, что адрес победителя, извлеченный из текущей транзакции, совпадает с адресом, извлеченным из пруфов
   && extract(getString(d.data, "winner")) == toBase58String(address.bytes)
   && newPrice > extract(getInteger(this, "price"))
   #проверяем, что транзакция подписана
   && sigVerify(d.bodyBytes, d.proofs[0], d.proofs[1])
   #проверяем корректность транзакции, указанной в пруфах
   && match proofTx {
     case tr : TransferTransaction =>
       tr.sender == address &&
       tr.amount == newPrice
     case _ => false
   }
 case t: TransferTransaction =>
 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
 || (
   height > endHeight
   && extract(getString(this, "winner")) == toBase58String((addressFromRecipient(t.recipient)).bytes)
   && t.assetId == token
   && t.amount == 1
 )
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Asirans / Crowdfunding

Ann konsidere yon sitiyasyon kote ou bezwen asire byen itilizatè yo kont pèt finansye. Pou egzanp, yon itilizatè vle yon garanti ke si yon siy depresyasyon, li pral kapab jwenn tounen kantite lajan total peye pou siy sa yo, epi li vle peye yon kantite lajan rezonab nan asirans.

Pou aplike sa a, yo dwe bay "jeton asirans" yo. Lè sa a, yon script enstale sou kont titulaire a, ki pèmèt sèlman sa yo Echanj Tranzaksyon ki satisfè sèten kondisyon yo dwe egzekite.

Pou anpeche depans doub, ou bezwen mande itilizatè a voye yon DataTransaction nan kont kontraktè a davans ak (kle, valè) = (purchaseTransactionId, sellOrderId) epi entèdi voye DataTransactions ak yon kle ki te deja itilize.

Se poutèt sa, prèv itilizatè a dwe genyen ID tranzaksyon achte siy asirans lan. Pè lajan an dwe menm jan ak tranzaksyon acha a. Pri a dwe egal ak sa ki fiks nan moman acha a, mwens pri asirans lan.

Li konprann ke imedyatman kont asirans lan achte marqueur asirans nan men itilizatè a nan yon pri ki pa pi ba pase youn nan kote li te achte yo: kont asirans lan kreye yon EchanjTranzaksyon, itilizatè a siyen lòd la (si tranzaksyon an fini kòrèkteman), la. kont asirans siyen dezyèm lòd la ak tranzaksyon an antye epi voye li nan blockchain la.

Si pa gen okenn acha rive, itilizatè a ka kreye yon Tranzaksyon Echanj dapre règ ki dekri nan script la epi voye tranzaksyon an nan blockchain la. Nan fason sa a itilizatè a ka retounen lajan an te depanse sou acha a nan marqueur asirans.

let insuranceToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
let freezePeriod = 150000
let insurancePrice = 10000
match tx {
 
 #убеждаемся, что, если поступила дата-транзакция, то у нее ровно одно поле и в стейте еще нет такого ключа
 case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key))
 case e : ExchangeTransaction =>
 
   #если у транзакции нет седьмого пруфа, проверяем корректность подписи
   if !isDefined(e.proofs[7]) then
     sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey)
   else
     #если у транзакции есть седьмой пруф, извлекаем из него транзакцию и узнаём её высоту
     let purchaseTx = transactionById(e.proofs[7])
     let purchaseTxHeight = extract(transactionHeightById(e.proofs[7]))
    
     #обрабатываем транзакцию из пруфа
     match purchaseTx {
       case purchase : ExchangeTransaction =>
         let correctSender = purchase.sender == e.sellOrder.sender
         let correctAssetPair = e.sellOrder.assetPair.amountAsset == insuranceToken &&
                                purchase.sellOrder.assetPair.amountAsset == insuranceToken &&
                                e.sellOrder.assetPair.priceAsset == purchase.sellOrder.assetPair.priceAsset
         let correctPrice = e.price == purchase.price - insurancePrice && e.amount == purchase.amount
         let correctHeight = height > purchaseTxHeight + freezePeriod
 
         #убеждаемся, что в транзакции-пруфе указан верный ID текущей транзакции
         let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.sellOrder.id
         correctSender && correctAssetPair && correctPrice && correctHeight && correctProof
     case _ => false
   }
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Yon siy asirans ka fè yon avantaj entelijan, pou egzanp, entèdi transfè li bay twazyèm pati.

Konplo sa a kapab aplike tou pou tokens crowdfunding, ki tounen bay pwopriyetè yo si kantite lajan ki nesesè yo pa te kolekte.

Taks sou tranzaksyon yo

Kontra entelijan yo aplikab tou nan ka kote li nesesè pou kolekte taks sou chak tranzaksyon ak plizyè kalite byen. Sa a ka fè atravè yon nouvo avantaj ak enstale parennaj pou tranzaksyon ak byen entelijan:

1. Nou bay FeeCoin, ki pral voye bay itilizatè yo nan yon pri fiks: 0,01 WAVES = 0,001 FeeCoin.

2. Mete parennaj pou FeeCoin ak echanj pousantaj: 0,001 WAVES = 0,001 FeeCoin.

3. Mete script sa a pou avantaj entelijan an:

let feeAssetId = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
let taxDivisor = 10
 
match tx {
  case t: TransferTransaction =>
    t.feeAssetId == feeAssetId && t.fee == t.amount / taxDivisor
  case e: ExchangeTransaction | MassTransferTransaction => false
  case _ => true
}

Kounye a chak fwa yon moun transfere N byen entelijan, y ap ba w FeeCoin nan kantite N/taxDivisor (ki ka achte nan men w nan 10 *N/taxDivisor WAVES), epi w ap bay minè a N/taxDivisor WAVES. Kòm yon rezilta, pwofi ou (taks) yo pral 9*N / taxDivisor WAVES.

Ou kapab tou fè taksasyon lè l sèvi avèk yon script avantaj entelijan ak MassTransferTransaction:

let taxDivisor = 10
 
match tx {
  case t : MassTransferTransaction =>
    let twoTransfers = size(t.transfers) == 2
    let issuerIsRecipient = t.transfers[0].recipient == addressFromString("3MgkTXzD72BTfYpd9UW42wdqTVg8HqnXEfc")
    let taxesPaid = t.transfers[0].amount >= t.transfers[1].amount / taxDivisor
    twoTransfers && issuerIsRecipient && taxesPaid
  case _ => false
}

Cashback ak pwogram lwayote

Cashback se yon kalite pwogram lwayote kote achtè a jwenn tounen yon pati nan kantite lajan an te depanse nan yon pwodwi oswa sèvis.

Lè n ap aplike ka sa a lè l sèvi avèk yon kont entelijan, nou dwe tcheke prèv yo menm jan nou te fè nan ka asirans lan. Pou anpeche depans doub, itilizatè a dwe voye yon DataTransaction ak (kle, valè) = (purchaseTransactionId, cashbackTransactionId) anvan li resevwa kachbak.

Nou dwe tou mete yon entèdiksyon sou kle ki deja egziste lè l sèvi avèk DataTransaction. cashbackDivisor - inite divize pa pataje kachbak la. Moun sa yo. si pati nan kachbak se 0.1, Lè sa a, cashbackDivisor 1 / 0.1 = 10.

let cashbackToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf'
 
#извлекаем из транзакции адрес отправителя
let this = extract(tx.sender)
let cashbackDivisor = 10
match tx {
 
 #убеждаемся, что, если поступила дата-транзакция, то у нее ровно одно поле и в стейте еще нет такого ключа
 case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key))
 case e : TransferTransaction =>
 
   #если у транзакции нет седьмого пруфа, проверяем корректность подписи
   if !isDefined(e.proofs[7]) then
     sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey)
   else
 
     #если у транзакции есть седьмой пруф, извлекаем из него транзакцию и узнаём её высоту
     let purchaseTx = transactionById(e.proofs[7])
     let purchaseTxHeight = extract(transactionHeightById(e.proofs[7]))
    
     #обрабатываем транзакцию из пруфа
     match purchaseTx {
       case purchase : TransferTransaction =>
         let correctSender = purchase.sender == e.sender
         let correctAsset = e.assetId == cashbackToken
         let correctPrice = e.amount == purchase.amount / cashbackDivisor
 
         #убеждаемся, что в транзакции-пруфе указан верный ID текущей транзакции
         let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.id
         correctSender && correctAsset && correctPrice && correctProof
     case _ => false
   }
 case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
}

Boukante atomik

Boukante atomik pèmèt itilizatè yo fè echanj byen san èd nan yon echanj. Avèk yon swap atomik, tou de patisipan yo nan tranzaksyon an oblije konfime li nan yon sèten peryòd tan.

Si omwen youn nan patisipan yo pa bay konfimasyon kòrèk tranzaksyon an nan tan yo te bay pou tranzaksyon an, tranzaksyon an anile epi echanj la pa fèt.

Nan egzanp nou an, nou pral itilize script kont entelijan sa a:

let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8')
let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg')
 
let beforeHeight = 100000
 
let secret = base58'BN6RTYGWcwektQfSFzH8raYo9awaLgQ7pLyWLQY4S4F5'
match tx {
  case t: TransferTransaction =>
    let txToBob = t.recipient == Bob && sha256(t.proofs[0]) == secret && 20 + beforeHeight >= height
    let backToAliceAfterHeight = height >= 21 + beforeHeight && t.recipient == Alice
    txToBob || backToAliceAfterHeight
  case _ => false
}

Nan pwochen atik la nou pral gade sou itilizasyon kont entelijan nan enstriman finansye tankou opsyon, avni ak bòdwo.

Sous: www.habr.com

Add nouvo kòmantè