ūüáßūüá∑ Tutorial Marlowe 11/14

Conte√ļdo no Blog: https://educacaocardano.wordpress.com/2020/06/15/marlowe-11/

11. Potenciais problemas com contratos

A linguagem Marlowe foi projetada para ter o m√≠nimo poss√≠vel de armadilhas e truques, para que os contratos possam ser escritos intuitivamente, evitando surpresas. No entanto, √© imposs√≠vel, por design, excluir todos os contratos que n√£o devem ser escritos, sem tornar o Marlowe muito mais dif√≠cil de usar. Al√©m disso, mesmo quando um contrato √© bem escrito, ainda √© poss√≠vel que seus usu√°rios interajam com ele de formas inv√°lidas, emitindo transa√ß√Ķes inv√°lidas.

Em todos os casos, quando esses efeitos indesejados acontecem, o Marlowe √© projetado para se comportar da maneira mais intuitiva e conservadora poss√≠vel. No entanto, vale a pena conhecer esses poss√≠veis problemas e revisar como Marlowe se comporta nessas situa√ß√Ķes. Esse √© o assunto deste tutorial.

11.1 Advertências

Os avisos de Marlowe s√£o indica√ß√Ķes de que um contrato foi escrito incorretamente. Um contrato bem escrito nunca deve emitir um aviso, n√£o importa como os usu√°rios interajam com ele. Idealmente, gostar√≠amos de proibir que contratos que possam emitir avisos sejam sempre escritos, mas isso exigiria que os contratos da Marlowe fossem digitados com depend√™ncia, e escrever express√Ķes com digita√ß√£o dependente √© muito mais complicado.

Em vez disso, Marlowe permite que contratos que emitem avisos sejam escritos, e fornecemos ferramentas de análise estática que permitem que os desenvolvedores de contratos verifiquem se um contrato específico pode emitir avisos. Além disso, fornecemos comportamentos de reserva para quando um contrato produz um aviso, apesar de nossos conselhos. Nós fornecemos comportamentos de reserva porque reconhecemos que a análise de grandes contratos pode ser muito computacionalmente cara e porque erros podem ser cometidos. Queremos que contratos mal escritos falhem da maneira mais inofensiva possível, isto é, conservadoramente.

Pagamentos n√£o positivos

Quando um contrato deve pagar uma quantia em dinheiro que seja menor que uma unidade de uma moeda ou token, ele emitir√° um aviso NonPositivePay e n√£o transferir√° nenhum dinheiro.

Os pagamentos negativos devem ser implementados como depósitos positivos (ao pagar um participante) ou pagamentos positivos na direção oposta (ao pagar entre contas).

Depósitos não positivos

Quando um contrato deve esperar uma quantia em dinheiro que seja menor que uma unidade de uma moeda de token, ele ainda aguardar√° uma transa√ß√£o IDeposit, mas essa transa√ß√£o n√£o precisa transferir nenhum dinheiro para o contrato e nenhum dinheiro √© transferido para o participante que emite a transa√ß√£o. Depois que esse dep√≥sito ‚Äúfalso‚ÄĚ for bem-sucedido, o contrato emitir√° um aviso NonPositiveDeposit.

Depósitos negativos sempre devem ser implementados como pagamentos positivos.

Pagamento parcial

Quando um contrato deve pagar uma quantia maior que a quantia existente na conta de origem, ele transferirá apenas o que estiver disponível nessa conta, mesmo que haja dinheiro suficiente em todas as contas da conta de origem. contrato e emitirá um aviso PartialPay.

Pagamentos parciais devem ser evitados porque um contrato que nunca produz um pagamento parcial √© um contrato expl√≠cito. Contratos expl√≠citos garantem a seus usu√°rios que eles ser√£o execut√°veis ‚Äč‚Äče que, em qualquer parte do contrato, diz que um pagamento ocorrer√°, isso realmente acontecer√°.

Sombreamento Let (n√£o coberto pela an√°lise est√°tica)

Quando um contrato atinge uma construção Let que redefine um valor com um identificador que já foi definido por uma Let externa, o contrato emitirá um aviso de Shadowing (Sombreamento) e substituirá a definição anterior.

O sombreamento é uma prática ruim de programação porque leva à confusão. O uso do mesmo identificador para mais de uma coisa pode induzir os desenvolvedores ou usuários a pensarem que um uso de Use será avaliado em uma quantidade, enquanto na verdade será avaliado em outra quantidade.

11.2 Cheiros ruins

Existem outros ‚Äúmaus cheiros‚ÄĚ que indicam que um contrato provavelmente foi mal projetado.

Esses contratos são válidos, no sentido de que não causam necessariamente avisos e fazem o que dizem que fazem, mas têm características que sugerem que o desenvolvedor do contrato não estava totalmente ciente das consequências do contrato, ou que o desenvolvedor propositalmente escreveu o contrato de uma maneira que foi confusa para o leitor.

Uso indefinido do Let (deve ser um aviso)

Quando uma construção Use usa um identificador que ainda não foi definido, ele será avaliado como o valor padrão de 0. Nenhum aviso será emitido, mas, novamente, essa é uma prática ruim, pois pode ser enganosa. (Constant 0) deve ser usado, pois torna explícita a quantidade em questão.

Partes inacessíveis de um contrato

Este é o principal mau cheiro nos contratos da Marlowe. Se parte do contrato é inacessível, por que teria sido incluído em primeiro lugar?

Esse mau cheiro assume v√°rias formas.

O subcontrato não está acessível

Por exemplo:

O contrato anterior é equivalente ao contract2. Em geral, você nunca deve usar FalseObs e deve usar TrueObs apenas como a observação raiz de uma construção Case.

A Observation é sempre curta

Por exemplo:

A observação anterior é equivalente à observation1. Novamente, você só deve usar TrueObs como a observação raiz de uma construção Case.

Ramo When está inacessível

Por exemplo:

contract2 é inacessível, todo o Case pode ser removido do contrato e o comportamento seria o mesmo.

O Value nunca é avaliado

Por exemplo:

value1 nunca ser√° avaliado. Mas, neste caso, n√£o temos escolha, a n√£o ser escrever algo no valor padr√£o de ChoiceValue

Nas vers√Ķes futuras do Marlowe, podemos remover o valor padr√£o para ChoiceValue e introduzir uma constru√ß√£o Value especial para esse tipo de situa√ß√£o.

Tempo limite aninhado sem aumento

Por exemplo:

contract1 está inacessível: após o bloco 10, o contrato evoluirá diretamente para contract2. O When interior não faz nenhuma diferença para o contrato.

11.3 Problemas de usabilidade

Mesmo que um contrato evite avisos e n√£o tenha um c√≥digo inacess√≠vel, ele ainda poder√° permitir que usu√°rios mal-intencionados for√ßam outros usu√°rios a situa√ß√Ķes indesej√°veis que n√£o foram originalmente planejadas pelo desenvolvedor do contrato.

Momento incorreto das constru√ß√Ķes When

Considere o seguinte contrato:

Em princ√≠pio, n√£o h√° nada de errado com este contrato, mas se (Papel ‚Äúalice‚ÄĚ) fizer sua escolha no bloco 9, ser√° praticamente imposs√≠vel para bob fazer sua escolha no prazo e receber o reembolso do dinheiro em sua conta (AccountId 1 (Papel ‚Äúbob‚ÄĚ)). A menos que isso fa√ßa parte de um jogo e que seja um efeito pretendido, √© prov√°vel que seja um contrato injusto para (Papel ‚Äúbob‚ÄĚ).

Em geral, √© uma boa pr√°tica garantir que as constru√ß√Ķes When tenham tempos limite crescentes e que o aumento entre os tempos limite seja razo√°vel para as diferentes partes emitirem e conseguirem que suas transa√ß√Ķes sejam aceitas pelo blockchain. H√° muitas raz√Ķes pelas quais a participa√ß√£o de uma parte pode ser adiada: uma falha no fornecimento de energia, um pico repentino no n√ļmero de transa√ß√Ķes pendentes no blockchain, ataques √† rede etc. Por isso, √© importante permitir bastante tempo e estar generoso com tempos limite e com aumentos nos tempos limites.

11.4 Erros

Finalmente, mesmo que um contrato esteja perfeitamente escrito. Os usu√°rios podem us√°-lo incorretamente e chamamos esses erros de uso incorreto.

Em todos os casos, sempre que uma transa√ß√£o causar um erro, a transa√ß√£o n√£o ter√° efeito no Contract ou em seu State. De fato, a carteira de um usu√°rio saber√° com anteced√™ncia se uma transa√ß√£o produzir√° um erro, porque as transa√ß√Ķes s√£o determin√≠sticas, portanto, os usu√°rios nunca precisar√£o enviar uma transa√ß√£o incorreta para o blockchain.

Intervalo ambíguo

Quando uma transa√ß√£o atinge um tempo limite, seu intervalo de slot deve ser inequ√≠voco sobre se o tempo limite passou ou n√£o. Por exemplo, se o limite m√°ximo de When de um contrato tiver tempo limite 10 e uma transa√ß√£o com intervalo de espa√ßo [6, 14] for emitida, a transa√ß√£o causar√° um erro AmbiguousSlotIntervalError, porque √© imposs√≠vel saber se o tempo limite passou apenas olhando para a transa√ß√£o. Para evitar isso, a transa√ß√£o deve ser dividida em duas transa√ß√Ķes separadas:

Um com intervalo de slot [6, 9].

Outro com intervalo de fenda [10, 14].

Aplicar sem correspondência

Se uma transação não fornecer as entradas esperadas pelo Contract, o contrato emitirá um erro NoMatchError e a transação inteira será descartada.

Transa√ß√£o in√ļtil

Se uma transa√ß√£o n√£o afetar o Contract ou o State, isso resultar√° em um erro Transaction Useless e a transa√ß√£o inteira ser√° descartada. A raz√£o pela qual descartamos transa√ß√Ķes in√ļteis √© que elas abrem a porta para ataques de nega√ß√£o de servi√ßo (DoS), porque um invasor em potencial pode inundar o contrato com transa√ß√Ķes desnecess√°rias e impedir transa√ß√Ķes necess√°rias de ingressar no blockchain.