> ## Documentation Index
> Fetch the complete documentation index at: https://docs.intention.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Serviços de programa

> Serviços que derivam o estado das contas a partir do histórico de negociação confirmado, fora do bloco, e devolvem o resultado à cadeia através de transações de protocolo.

Há coisas que uma plataforma de negociação precisa de saber sobre uma conta e que não podem ser calculadas enquanto um bloco executa. Um escalão de volume depende de trinta dias de negociação. Uma recompensa depende de uma janela que ainda não fechou. Uma atribuição de referências depende de uma relação estabelecida há meses.

Colocar esse trabalho dentro da execução do bloco seria errado por duas razões: obrigaria todos os blocos a pagar por um cálculo de que quase nenhum bloco precisa e exigiria que o kernel guardasse histórico que não tem outro motivo para guardar.

Os serviços de programa resolvem-no invertendo a direção. O cálculo corre **fora** do bloco, sobre o registo confirmado. O seu *resultado* é depois gravado **de volta** na cadeia como estado de protocolo, onde a execução o pode ler em tempo constante como qualquer outra configuração.

<div className="dg" data-dg="program-writeback">
  <div className="dg-c" style={{aspectRatio:"720 / 348"}}>
    <svg className="dg-w" viewBox="0 0 720 348" aria-hidden="true">
      <path className="dg-wire" d="M 144.00 70.00 L 169.60 70.00" />

      <path className="dg-head" d="M 176.00 70.00 L 169.60 74.40 L 169.60 65.60 Z" />

      <path className="dg-wire dg--sky" d="M 344.00 70.00 L 369.60 70.00" />

      <path className="dg-head dg--sky" d="M 376.00 70.00 L 369.60 74.40 L 369.60 65.60 Z" />

      <path className="dg-wire" d="M 534.00 70.00 L 561.75 38.78" />

      <path className="dg-head" d="M 566.00 34.00 L 565.04 41.71 L 558.46 35.86 Z" />

      <path className="dg-wire dg--blue" d="M 534.00 70.00 L 561.33 95.62" />

      <path className="dg-head dg--blue" d="M 566.00 100.00 L 558.32 98.83 L 564.34 92.41 Z" />

      <path className="dg-wire dg--blue" d="M 645.00 128.00 L 645.00 136.00 L 465.00 136.00 L 465.00 142.00" />

      <path className="dg-head dg--blue" d="M 465.00 142.00 L 460.60 135.60 L 469.40 135.60 Z" />

      <path className="dg-wire dg--green" d="M 554.00 181.00 L 567.60 181.00" />

      <path className="dg-head dg--green" d="M 574.00 181.00 L 567.60 185.40 L 567.60 176.60 Z" />
    </svg>

    <div className="dg-b" style={{left:"0.0000%",top:"11.4943%",width:"19.4444%",height:"17.2414%"}}><span className="dg-t">Histórico confirmado</span></div>
    <div className="dg-b dg--sky" style={{left:"25.0000%",top:"5.7471%",width:"22.2222%",height:"28.7356%"}}><span className="dg-t">Serviço de programa</span><span className="dg-s">cálculo por janela, fora do bloco</span><span className="dg-n">lê a tabela de comissões em direto da cadeia</span></div>
    <div className="dg-b dg--yellow dg-round" style={{left:"52.7778%",top:"10.3448%",width:"20.8333%",height:"19.5402%"}}><span className="dg-t">Mudou desde a última aplicação?</span></div>
    <div className="dg-b" style={{left:"79.1667%",top:"2.8736%",width:"20.8333%",height:"13.7931%"}}><span className="dg-t">Nada é escrito</span></div>
    <div className="dg-b dg--blue" style={{left:"79.1667%",top:"21.8391%",width:"20.8333%",height:"13.7931%"}}><span className="dg-t">Transação de protocolo</span></div>
    <div className="dg-b dg--green" style={{left:"52.7778%",top:"41.9540%",width:"23.6111%",height:"20.1149%"}}><span className="dg-t">Estado da cadeia</span></div>
    <div className="dg-b dg--green" style={{left:"80.2778%",top:"41.9540%",width:"19.7222%",height:"20.1149%"}}><span className="dg-t">Lido durante a execução</span><span className="dg-s">em tempo constante</span></div>
    <div className="dg-b dg-dashed dg-left" style={{left:"0.0000%",top:"70.1149%",width:"48.8889%",height:"24.1379%"}}><span className="dg-t">Comparar taxas, não posições de escalão</span><span className="dg-s">Um limiar que se desloca, ou um escalão cuja taxa muda, altera o que uma conta paga sem alterar o seu índice de escalão.</span></div>
    <div className="dg-b dg-dashed dg-left" style={{left:"51.1111%",top:"70.1149%",width:"48.8889%",height:"24.1379%"}}><span className="dg-t">A cadeia resolve a taxa final</span><span className="dg-s">Um período só é registado como aplicado depois de todos os lotes serem confirmados; uma falha reexecuta o período inteiro — seguro, porque o cálculo é idempotente.</span></div>
  </div>
</div>

A cadeia continua a ser a autoridade. Um serviço não guarda estado de que a rede dependa — propõe um valor, e só o que a cadeia aceitou é real.

<h2 id="what-runs-today">
  O que está em funcionamento hoje
</h2>

**Escalões de comissões por volume.** O serviço consome o histórico de negociação transmitido por um nó, acumula o volume por conta e regista instantâneos com uma periodicidade definida. Quando um período fecha, calcula o volume de cada conta na janela móvel, mapeia-o através da configuração de comissões **lida em direto da cadeia** e escreve de volta, em lotes, as contas que mudaram.

Vários pormenores desta frase são determinantes:

* **A tabela de escalões é lida da cadeia, nunca fixada no código.** Um serviço com uma cópia própria continuaria a aplicar a tabela de ontem depois de a rede a ter alterado.
* **A comparação é feita sobre as taxas, não sobre as posições dos escalões.** Comparar *índices* de escalão deixa escapar dois casos reais: um limiar que se desloca e faz uma conta inalterada cair noutro escalão, e um escalão cuja taxa muda sem que o índice mude. Ambos alteram o que uma conta paga; nenhum altera o índice.
* **A cadeia resolve a taxa final.** A transação transporta um índice de escalão; a execução resolve-o pela configuração de comissões em vigor. Um índice de escalão fora do intervalo válido faz falhar o lote inteiro, em vez de ser aplicado parcialmente.
* **Um período só é registado como aplicado depois de todos os lotes serem confirmados.** Uma falha a meio do período faz reexecutar o período inteiro, o que é seguro porque o cálculo é idempotente — a mesma janela produz o mesmo resultado.

<h2 id="the-failure-model">
  O modelo de falhas
</h2>

Estes serviços situam-se entre dois sistemas que, em algum momento, estarão indisponíveis. O desenho parte desse princípio, em vez de tratar a indisponibilidade como excecional.

As falhas de dependências — a base de dados, o fluxo do nó, a API do nó — são repetidas com espera crescente (backoff). Não terminam o processo, porque um reinício não repara uma dependência inacessível; limita-se a somar um arranque a frio à indisponibilidade. Continua a ser fatal aquilo que um reinício *pode* corrigir ou que um operador tem de ver: configuração inválida no arranque, incapacidade de abrir o endpoint de saúde e panics.

Durante uma indisponibilidade, o processo mantém-se a correr, declara-se não pronto e contabiliza erros. O sinal operacional é, por isso, **«já está há N minutos sem estar pronto?»** e não **«o processo está vivo?»** — que é a pergunta útil, já que um processo vivo que há uma hora não consegue ingerir dados é o incidente real.

O encerramento é controlado perante os sinais que um orquestrador envia: o trabalho para, os checkpoints são gravados e o processo termina de forma limpa. Sem isso, cada implantação de rotina custaria uma janela por gravar e uma reexecução.

<Note>
  Um período que foi calculado mas ainda não aplicado não é um período perdido. Como o cálculo é idempotente e o período aplicado só é registado depois de a escrita ter sucesso, uma execução interrompida retoma refazendo a janela, em vez de a saltar.
</Note>

<h2 id="why-the-pattern-generalizes">
  Porque o padrão se generaliza
</h2>

O caminho de escrita de volta é genérico. Existem transações de protocolo para definir configuração ao nível da conta e para definir configuração global, e um serviço de programa é qualquer processo que calcule um valor para uma delas a partir do histórico confirmado.

Os escalões de comissões são o único caso em funcionamento. Programas de incentivos, atribuição de referências e elegibilidade para campanhas teriam a mesma forma: um cálculo por janela sobre o histórico de negociação, uma comparação com o que está atualmente aplicado e uma escrita de volta em lotes. Pertenceriam aqui, e não ao kernel, pela mesma razão que os escalões de comissões — o cálculo é periódico e histórico, ao passo que a execução precisa de que a resposta seja uma consulta em tempo constante. Nenhum deles está construído; o que se generaliza é o padrão, não um compromisso de que virão a usá-lo.

As condições comerciais destes programas estão em [Comissões de negociação](/pt/programs/fees). Esta página trata de como o resultado chega à cadeia.

<h2 id="where-to-go-next">
  Para onde ir a seguir
</h2>

<CardGroup cols={2}>
  <Card title="Indexador" href="/pt/protocol/architecture/indexer">
    O fluxo que estes serviços consomem.
  </Card>

  <Card title="Comissões" href="/pt/programs/fees">
    O lado comercial: quais são os escalões e quanto custam.
  </Card>

  <Card title="IntentionKernel" href="/pt/protocol/architecture/kernel">
    Como a configuração escrita de volta é lida durante a execução.
  </Card>

  <Card title="Modelo de estado" href="/pt/protocol/architecture/state/model">
    Porque as chaves de configuração são versionadas e porque os clientes as devem resolver em direto.
  </Card>
</CardGroup>
