LusoCryptoLabs

Notas de campo

O que só se aprende
a correr a coisa.

Uma regra: cada entrada traz o número a que foi medida.

Isto não são opiniões sobre blockchains. São coisas que eram verdade num dia concreto, contra um nó a sério, quase sempre descobertas porque alguma coisa falhou de uma forma que não dizia nada de útil sobre porquê.

Quando o achado era de um projecto de outra pessoa, o reporte está ligado no fim da entrada. Quando encontrámos alguma coisa e não a levámos a lado nenhum, também se diz.

2026-09-12Nervos CKB

Lemos uma configuração velha e chamámos-lhe biblioteca partida. Não era

Esta entrada esteve errada durante um dia, e a correcção vale mais do que a afirmação valia.

O CCC é a biblioteca com que a maioria das aplicações Nervos constrói transacções. Para o JoyID em mainnet distribui cinco cell deps fixos, e fomos verificá-los contra a chain: os cinco outpoints estão gastos, na 1.12.5 e na 1.20.1. Essa parte é verdade e continua a ser. Concluímos que uma transacção de mainnet que precisasse daquele lock seria rejeitada, e reportámos.

a configuração estática 0x8a605a44…:0-4 todos gastos o que o construtor põe na tx 0x673e1843…:0-4 todos vivos

O maintainer respondeu que o getCellDeps resolve cada dep pelo type id antes de o usar, portanto o outpoint velho nunca chega a uma transacção. Testámos o caminho que uma aplicação percorre de facto: o prepareTransaction do signer do JoyID chama o addCellDepsOfKnownScripts, que resolve, e a transacção construída leva as células vivas. Ele tinha razão. Não está nada partido, e a correcção que tínhamos escrito para nós era redundante.

A lição é aquela para que esta página existe. Verificámos um valor e não um caminho. Um número velho num ficheiro de configuração só é um bug se alguma coisa o usar tal como está escrito, e confirmar se alguma coisa o usa era mais um passo do que demos. O issue fica aberto como pedido de documentação, que é o que devia ter sido desde o início.

Reportado, depois corrigido: ckb-devrel/ccc#531

2026-09-12Nervos CKB

Um contrato não consegue verificar uma witness de 64 KiB, e o erro não fala de tamanho

Estávamos a dimensionar uma segunda imagem para um perfil on-chain e queríamos o tecto real. Um type script carrega a witness numa alocação só, e fá-lo mais do que uma vez por execução. O alocador arredonda cada pedido para a potência de dois seguinte, portanto no momento em que a witness passa 64 KiB cada uma dessas alocações duplica e a heap esgota-se. O script sai com -1.

witness de 64 593 B -> ACEITE witness de 65 617 B -> Inputs[0].Type, erro -1

A fronteira é 65 536, exactamente. Nada no erro fala em bytes, portanto visto de fora parece um bug do contrato e não um orçamento.

2026-09-12Método

Um limite medido sem correr os scripts não é um limite

O nosso próprio SDK carregava um tecto de 500 KB há meses, obtido honestamente: um script construía transacções cada vez maiores e media-as contra o que cabe num bloco. O cabeçalho dele até dizia isso mesmo, que nada era assinado nem enviado.

Isso mede o bloco. E o bloco não é a primeira parede. Pedir a um nó que corresse mesmo os scripts pôs o tecto real em 52 KB, nove vezes mais baixo, e a falha acima disso é um -1 pelado. A verificação nunca esteve errada; estava a responder a uma pergunta diferente daquela que toda a gente lia nela.

acreditava-se 500 KB (transacções construídas e medidas) real 52 KB (test_tx_pool_accept, scripts corridos)
2026-09-12CKBFS

Ao publicar um ficheiro na chain há dois tectos empilhados, e nenhum está documentado

O CKBFS guarda ficheiros nas witnesses das transacções. Publicar um esbarra em duas paredes independentes, encontradas com o estimador de ciclos de um nó, portanto sem custo nenhum:

o contrato: no máximo 8 witnesses de conteúdo por transacção (é uma contagem, não um tamanho: 8 x 20 KB passa, 9 x 20 KB falha) o lock: uma assinatura sobre uma witness muito acima de 32 KB falha, erro -22 na prática: 240 000 bytes por transacção de publicação

Ambos aparecem como códigos de erro nus. Encontrámos também que um leitor conforme tem de verificar o checksum que cada backlink declara para tudo o que foi publicado antes dele, e não só a soma final, senão um histórico adulterado lê-se como válido.

Reportado: code-monad/ckbfs#3

2026-09-12Nervos CKB

Um comentário muda os bytes que estão na chain

Contratos em Rust compilados com verificação de overflow enterram uma localização de pânico, ficheiro e número de linha, em cada verificação de limites. Mexe-se numa linha de uma crate partilhada e todos os contratos que a ligam saem com bytes diferentes, sem mudança nenhuma na lógica nem no código deles.

um comentário acrescentado a uma crate partilhada -> 1 byte diferente em 39 888, na posição 0xdc0 -> o número de linha 625 passou a 626

O custo não é o byte. É que verificar um contrato publicado contra o código actual passa a reportar divergência por causa de um comentário, o que treina quem lê aquilo a encolher os ombros perante um sinal vermelho. Mudámos a pergunta que a ferramenta faz: não "isto é igual ao que o código compila hoje" mas "isto é igual ao que compila o commit de onde saiu".

2026-09-12Segurança

Uma política de conteúdo com cara de cuidadosa pode partir todas as páginas que protege

Servir um documento escrito por outra pessoa, a partir de um host teu, é o sítio onde uma política estrita ganha o ordenado. A nossa saiu como sandbox allow-scripts; default-src 'self' data:, que parece responsável e deitou fora o estilo inline da própria página, em silêncio. A primeira renderização foi texto em serifas sem estilo, sem nada registado em lado nenhum.

Uma página de ficheiro único guardada numa chain é CSS inline quase por definição, portanto essa política não endurece essas páginas, parte-as todas. É a sandbox que faz o trabalho de segurança; as directivas de origem decidem o que a página pode carregar. Trocar as duas coisas custa a página e não compra nada.

2026-09-12Ecossistema

Antes de construíres em cima, conta-lhe as transacções

Escolhemos um protocolo de ficheiros on-chain em vez de IPFS e Arweave, deliberadamente, e depois fomos ver em cima de que estávamos. Em mainnet, o code hash desse protocolo tem três transacções. Uma equipa, uma proposta de comunidade e não uma norma ratificada, repositórios com cerca de uma estrela.

Não mudou a decisão, porque a exposição é limitada: o leitor é nosso e os bytes estão no histórico da chain, portanto ler continua a funcionar mesmo que o projecto pare. O que mudou foi o risco ficar escrito onde a próxima pessoa o vai ler, em vez de ser ela a descobri-lo mais tarde.

PermanenteNota honesta

A maior parte do que aprendemos continua por partilhar

Os dois reportes acima foram ambos abertos no mesmo dia, o que te diz o estado verdadeiro disto: usámos este ecossistema intensamente durante dois anos e até agora devolvemos quase nada, porque o que aprendemos vivia em repositórios privados.

É essa a falha que esta página existe para fechar, e uma página não é o fecho todo. As medições acima já são públicas. Os leitores, as ferramentas e os remendos por trás delas, na maior parte, ainda não.